电脑取随机数是什么原理,是真正的随机数吗?

关注者
590
被浏览
121,681

16 个回答

首先,「真随机」也有不同的含义,若想要「真正的真随机」目测只能靠量子力学了。一般的所谓真随机不是指这个,而是指统计意义上的随机,也就是具备不确定性,可以被安全的用于金融等领域,下面说的也是这种。

答案是,计算机系统可以产生统计意义上的真随机数。

大部分程序和语言中的随机数(比如 C 中的,MATLAB 中的),确实都只是伪随机。是由可确定的函数(常用线性同余),通过一个种子(常用时钟),产生的伪随机数。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)。

直观来想,计算机是一种可确定,可预测的的设备,想通过一行一行的确定的代码自身产生真随机,显然不可能。但是,我们或许可以迂回一下……

实现方法简单说就是软硬结合,或者说,引入系统外的变量(把软件,代码,算法想象成一个封闭的系统)。

一个典型的例子就是 UNIX 内核中的随机数发生器(/dev/random),它在理论上能产生真随机。即这个随机数的生成,独立于生成函数,这时我们说这个产生器是非确定的。

具体来讲,UNIX 维护了一个熵池,不断收集非确定性的设备事件,即机器运行环境中产生的硬件噪音来作为种子。

比如说:时钟,IO 请求的响应时间,特定硬件中断的时间间隔,键盘敲击速度,鼠标位置变化,甚至周围的电磁波等等……直观地说,你每按一次键盘,动一下鼠标,邻居家 wifi 信号强度变化,磁盘写入速度,等等信号,都可能被用来生成随机数。

更具体的,内核提供了向熵池填充数据的接口:

比如鼠标的就是
void add_mouse_randomness(__u32 mouse_data) 

内核子系统和驱动调用这个函数,把鼠标的位置和中断间隔时间作为噪音源填充进熵池。

所以,结论是,程序和算法本身不能产生真随机,但是计算机系统作为整体可以迂回产生统计意义上的真随机。

参考:
  • 内核源码在/drivers/char/random.c
  • Windows 中也有相对的随机数生成器,基本的思想是一致的
  • 如果要求更高的话,也有专用的设备,可收集附近的电磁场等环境噪音来产生随机数
题目:电脑取随机数是什么原理,是真正的随机数吗?首先声明,这种问题维基解释的更好。
答案,不会扣源码自己出来看看吗?下面是VC++一直用的随机函数,就一行。你觉得他是真随机还是伪随机?
int __cdecl rand (
        void
        )
{
        _ptiddata ptd = _getptd();
 
        return( ((ptd->_holdrand = ptd->_holdrand * 214013L
            + 2531011L) >> 16) & 0x7fff );
}
这当然是伪随机。其实伪随机算法就那么几类,
1.线性同余,
2.平方取中,
3.其他

目前看到的大部分库的默认实现都是线性同余,怎么解释?看上面的例子就知道了。至于线性同余的弱点?既然是同余那么就别一个周期后,你产生的随机数又会重复出现了。这有什么影响吗?如果就是做个测试好玩,没啥影响,如果你是根据数字生产卡号,密码,影响就大了。(真事,当年一些电话卡被破解就是这样来的),这个就涉及伪随机的算法循环长度。什么叫循环长度?就是如果第一次产生数字55,第二个产生数字107,那么循环多少次后,会继续产生,55,107……这样的序列。
大部分简单算法的循环长度都是2^32左右。

那么有没有更好的算法。更好的循环长度让人无法破解呢。有。就是其他。其实数学界的人才很多的。推荐一个MT随机数算法。(Mersenne Twister),日本人发明的。 Mersenne Twister梅森旋转算法,这真不是在大家都反日的时候给大家添乱,这个算法的确是日本人发明的。而且还是目前可以看到最好随机数算法,欢迎爱国青年灭了他(找出比他更好的算法)Makoto Matsumoto(松本真) 和Takuji Nishimura(西村拓士)在1997年开发的,基于有限二进制字段上的矩阵线性递归field F_{2}。 可以快速产生高质量的伪随机数, 修正了古典随机数发生算法的很多缺陷。
这货的循环长度能到多少?一个常用的实现是产生32位数字,循环长度 2^19937。一般来说只要你不搞天文运算。都可以轻松应对了。当然这还不算什么,人家还快。这个算法的普通实现不必函数库的rand慢多少,大约只慢10%,而且这2个人了还搞了一个SSE的库(不好移植没用过),据说超快。
这已经是伪随机的最高峰(之一)了。

什么,你还不满意?那软件阵营已经无法帮助你了。找硬件把。