世界上真的有真随机数生成器存在么

几乎所有编程语言中都提供了"生成一个随机数"的方法,也就是调用这个方法会生成一个数,我们事先也不知道它生成什么数。比如在.Net中编写下面的代码:
Random rand = newRandom();
Console.WriteLine(rand.Next());
运行后结果如下:
&&&&Next()方法用来返回一个随机数。同样的代码你执行和我的结果很可能不一样,而且我多次运行的结果也很可能不一样,这就是随机数。
&&&&看似很简单的东西,使用的时候有陷阱。我编写下面的代码想生成100个随机数:
for(int i=0;i&100;i++)
Random rand = new Random();
Console.WriteLine(rand.Next());
&&&&太奇怪了,竟然生成的"随机数"有好多连续一样的,这算什么"随机数"呀。有人指点"把new Random()"放到for循环外面就可以了:
Random rand = newRandom();
for(int i=0;i&100;i++)
Console.WriteLine(rand.Next());
&&&&&运行结果:
&&&&确实可以了!&
二、这是为什么呢?
&&&&这要从计算机中"随机数"产生的原理说起了。我们知道,计算机是很严格的,在确定的输入条件下,产生的结果是唯一确定的,不会每次执行的结果不一样。那么怎么样用软件实现产生看似不确定的随机数呢?
&&&&生成随机数的算法有很多种,最简单也是最常用的就是&"线性同余法": &第n+1个数=(第n个数*29+37) % 1000,其中%是"求余数"运算符。很多像我一样的人见了公式都头疼,我用代码解释一下吧,MyRand是一个自定义的生成随机数的类:
class MyRand
public MyRand(int seed)
this.seed =
public int Next()
int next = (seed * 29 + 37) % 1000;
&如下调用:
MyRand rand = newMyRand(51);
for (int i = 0; i & 10; i++)
Console.WriteLine(rand.Next());
执行结果如下:
生成的数据是不是看起来"随机"了。简单解释一下这个代码:我们创建MyRand的一个对象,然后构造函数传递一个数51,这个数被赋值给seed,每次调用Next方法的时候根据(seed * 29 + 37) % 1000计算得到一个随机数,把这个随机数赋值给seed,然后把生成的随机数返回。这样下次再调用Next()的时候seed就不再是51,而是上次生成的随机数了,这样就看起来好像每一次生成的内容都很"随机"了。注意"%1000"取余预算的目的是保证生成的随机数不超过1000。&
当然无论是你运行还是我每次运行,输出结果都是一样的随机数,因为根据给定的初始数据51,我们就可以依次推断下来下面生成的所有"随机数"是什么都可以算出来了。这个初始的数据51就被称为"随机数种子",这一系列的516、1、66、951、616&&数字被称为"随机数序列"。我们把51改成52,就会有这样的结果:
三、楼主好人,跪求种子
&&&&那么怎么可以使得每次运行程序的时候都生成不同的"随机数序列"呢?因为我们每次执行程序时候的时间很可能不一样,因此我们可以用当前时间做"随机数种子"
MyRand rand = newMyRand(Environment.TickCount);
for (int i = 0; i & 10; i++)
Console.WriteLine(rand.Next());
&&&&&Environment.TickCount为"系统启动后经过的微秒数"。这样每次程序运行的时候Environment.TickCount都不大可能一样(靠手动谁能一微秒内启动两次程序呢),所以每次生成的随机数就不一样了。
&&&&当然如果我们把new MyRand(Environment.TickCount)放到for循环中:&
for (int i = 0; i & 100; i++)
MyRand rand = newMyRand(Environment.TickCount);
Console.WriteLine(rand.Next());
&&&&运行结果又变成"很多是连续"的了,原理很简单:由于for循环体执行很快,所以每次循环的时候Environment.TickCount很可能还和上次一样(两行简单的代码运行用不了一毫秒那么长事件),由于这次的"随机数种子"和上次的"随机数种子"一样,这样Next()生成的第一个"随机数"就一样了。从"-320"变成"-856"是因为运行到"-856"的时候时间过了一毫秒。&
四、各语言的实现
&&&&我们看到.Net的Random类有一个int类型参数的构造函数:
public&Random(int&Seed)
就是和我们写的MyRand一样接受一个"随机数种子"。而我们之前调用的无参构造函数就是给Random(int&Seed)传递Environment.TickCount类进行构造的,代码如下:
&&&&&&&&public&Random()&:&this(Environment.TickCount)&&&&&&&&{&&&&&&&&}
&&&&这下我们终于明白最开始的疑惑了。
同样道理,在C/C++中生成10个随机数不应该如下调用:
for(i=0;i&10;i++)
srand( (unsigned)time( NULL ) );
printf("%d\n",rand());
srand( (unsigned)time( NULL ) ); //把当前时间设置为"随机数种子"
for(i=0;i&10;i++)
printf("%d\n",rand());
&五、"奇葩"的Java
Java学习者可能会提出问题了,在Java低版本中,如下使用会像.Net、C/C++中一样产生相同的随机数:&
for(int i=0;i&100;i++)
Random rand = new Random();
System.out.println(rand.nextInt());
&因为低版本Java中Rand类的无参构造函数的实现同样是用当前时间做种子:
public&Random()&{&this(System.currentTimeMillis());&}&
但是在高版本的Java中,比如Java1.8中,上面的"错误"代码执行却是没问题的:
&&&&为什么呢?我们来看一下这个Random无参构造函数的实现代码:
public Random()
this(seedUniquifier() ^ System.nanoTime());
private static long seedUniquifier() {
for (;;) {
long current = seedUniquifier.get();
long next = current * 652981L;
if (pareAndSet(current, next))
privatestaticfinal AtomicLong seedUniquifier
= new AtomicLong(8012L);
&&&&&这里不再是使用当前时间来做"随机数种子",而是使用System.nanoTime()这个纳秒级的时间量并且和采用原子量AtomicLong根据上次调用构造函数算出来的一个数做异或运算。关于这段代码的解释详细参考这篇文章《》
最核心的地方就在于使用static变量AtomicLong来记录每次调用Random构造函数时使用的种子,下次再调用Random构造函数的时候避免和上次一样。
六、高并发系统中的问题
&&&&前面我们分析了,对于使用系统时间做"随机数种子"的随机数生成器,如果要产生多个随机数,那么一定要共享一个"随机数种子"才会避免生成的随机数短时间之内生成重复的随机数。但是在一些高并发的系统中一个不注意还会产生问题,比如一个网站在服务器端通过下面的方法生成验证码:
Random rand = new Random();
Int code = rand.Next();
&&&&当网站并发量很大的时候,可能一个毫秒内会有很多个人请求验证码,这就会造成这几个人请求到的验证码是重复的,会给系统带来潜在的漏洞。
&&&&&再比如我今天看到的一篇文章《当随机不够随机:一个在线扑克游戏的教训》里面就提到了"由于随机数产生器的种子是基于服务器时钟的,黑客们只要将他们的程序与服务器时钟同步就能够将可能出现的乱序减少到只有 200,000 种。到那个时候一旦黑客知道 5 张牌,他就可以实时的对 200,000 种可能的乱序进行快速搜索,找到游戏中的那种。所以一旦黑客知道手中的两张牌和 3 张公用牌,就可以猜出转牌和河牌时会来什么牌,以及其他玩家的牌。" &
&&&&这种情况有如下几种解决方法:
把Random对象作为一个全局实例(static)来使用。Java中Random是线程安全的(内部进行了加锁处理);.Net中Random不是线程安全的,需要加锁处理。不过加锁会存在会造成处理速度慢的问题。而且由于初始的种子是确定的,所以攻击者存在着根据得到的若干随机数序列推测出"随机数种子"的可能性。
因为每次生成Guid的值都不样,网上有的文章说可以创建一个Guid计算它的HashCode或者MD5值的方式来做种子:&new Random(Guid.NewGuid().GetHashCode())&。但是我认为Guid的生成算法是确定的,在条件充足的情况下也是可以预测的,这样生成的随机数也有可预测的可能性。当然只是我的猜测,没经过理论的证明。
采用"真随机数发生器",快看下一节分解!
&七、真随机数发生器
&&&&根据我们之前的分析,我们知道这些所谓的随机数不是真的"随机",只是看起来随机,因此被称为"伪随机算法"。在一些对随机要求高的场合会使用一些物理硬件采集物理噪声、宇宙射线、量子衰变等现实生活中的真正随机的物理参数来产生真正的随机数。
当然也有聪明的人想到了不借助增加"随机数发生器"硬件的方法生成随机数。我们操作计算机时候鼠标的移动、敲击键盘的行为都是不可预测的,外界命令计算机什么时候要执行什么进程、处理什么文件、加载什么数据等也是不可预测的,因此导致的CPU运算速度、硬盘读写行为、内存占用情况的变化也是不可预测的。因此如果采集这些信息来作为随机数种子,那么生成的随机数就是不可预测的了。
在Linux/Unix下可以使用"/dev/random"这个真随机数发生器,它的数据主来来自于硬件中断信息,不过产生随机数的速度比较慢。
Windows下可以调用系统的CryptGenRandom()函数,它主要依据当前进程Id、当前线程Id、系统启动后的TickCount、当前时间、QueryPerformanceCounter返回的高性能计数器值、用户名、计算机名、CPU计数器的值等等来计算。和"/dev/random"一样CryptGenRandom()的生成速度也比较慢,而且消耗比较大的系统资源。
当然.Net下也可以使用RNGCryptoServiceProvider&类(System.Security.Cryptography命名空间下)来生成真随机数,根据StackOverflow上一篇帖子介绍RNGCryptoServiceProvider&并不是对CryptGenRandom()函数的封装,但是和CryptGenRandom()原理类似。 &
有人可能会问:既然有"/dev/random" 、CryptGenRandom()这样的"真随机数发生器",为什么还要提供、使用伪随机数这样的"假货"?因为前面提到了"/dev/random" 、CryptGenRandom()生成速度慢而且比较消耗性能。在对随机数的不可预测性要求低的场合,使用伪随机数算法即可,因为性能比较高。对于随机数的不可预测性要求高的场合就要使用真随机数发生器,真随机数发生器硬件设备需要考虑成本问题,而"/dev/random"、CryptGenRandom()则性能较差。
万事万物都没有完美的,没有绝对的好,也没有绝对的坏,这才是多元世界美好的地方。
阅读(...) 评论()世界上有没有真正的随机事件? - 哲学 - 知乎
世界上有没有真正的随机事件? - 哲学 - 知乎
匿名用户、、这种说法不对。这种说法至多可以将统计现象和混沌现象算做伪随机。但是量子现象是真随机,并且有实验证明量子现象不是统计现象。也就是并没有一系列的确定算法可以模拟出量子现象。进而由于大多统计现象和混沌现象伴随着量子现象,他们大多也是真随机。物理真随机的两大来源是量子(核衰变,半透镜)和热运动(噪音)。、、我不同意量子现象就是真随机的观点。量子力学本身就是由一些经验上的公式构建起来的体系,我们都知道这套东西很好用,能解释实验上观察到的现象,但是我们对于为什么这些公式长成这个样子了解甚少,我们不知道这些公式背后的本质是什么,不能解释为什么有这些公式。所以说量子力学是一个很好用的但不成熟的科学,它连自己的本质都没解释清楚,结论都建立在一些基本假设之上,所以说虽然量子力学层面事件是按照概率发生的,但是比量子力学更底层的一些规律(未知的)有可能是决定论的,有可能是伪随机的。随便举个例子,你怎么证明黑客帝国的世界观是错的?现代科学无法证伪黑客帝国的世界观。存在这样一种可能,世界上所有的事件都是由某种超级计算机模拟出来的,量子力学只不过是这台计算机在运算时使用的一套规则,让我们人类感觉事件的发生是按照概率的,其实不是的,是这台超级计算机运算出来的,量子力学是我们的一种错觉。不要说我在扯淡,因为现代科学无法证明这种可能为零。知乎用户当然有,人类的出现本身就是一个随机事件。,我知道我不知道我知道我不知道、、匿名用户量子化……现在普遍还是认为,上帝是 掷骰子 的;波尔对爱因斯坦的反击 :“不用你告诉上帝该做什么!”,iZhihu 2.10 专栏:知乎用户、、赞同在世界的全部范围内——没有。以下推论以此信仰为基础:但同样没有知晓这个世界全部状态的可能。因此,在有限的可知范围内——有。科学,自然属于有限的可知范围。// 好吧,我的否定神的立场确实有点动摇了……知乎用户,骂就骂吧!赞同我认为整个世界事情都是随机的,只是某些情况下呈现出概率统计学这种不严格的决定论,从而宏观显示出确定性。量子力学和混沌学我觉得充分说明了世界的复杂性,随机性。拉普拉斯的妖又来啦~~很多人看来受牛顿的经典物理的影响很严重啊,受经验主义思想束缚,认为事物具有严格的决定论和因果律,从而衍生出一环扣一环的这种因果关系导致了决定论思想的产生。最好看看《量子力学史话》《物理科学与辩证法》,我想会有答案的。PS:楼上很多人把“不确定性原理”理解错啦!!!,法学在读研究生赞同看了所有的答案,发现一个问题,随机没有一个统一的定义,没有这个基础,所有的讨论都是盲目的,我们应该先把这个前提解决了。大概说一下自己的想法:定义:人们无法将一个事物的可能性空间控制在一定的范围内。1.好像有点唯心主义,我觉的唯心主义和唯物主义都不对。2.随着人的发展以前对人们是随机的事物可能变成确定,但人类的认识有局限性。当人类的任何观察手段都会对结果有巨大影响的时候,比如测不准定律。ps看控制论相关书籍时,来搜的这个问题,所以我也没有清晰、完整的观点,只是有感而发,表达能力很差,见谅。对这个问题感兴趣的,欢迎讨论。,Don't panic. Let's find the time machi…赞同第一个链接是conway的自由意志理论。简单说,conway这个理论就是说,任何符合他前提的物理理论都是“真随机”(观测结果不会被任何在观测前的因素影响)。大多数哲学家都不认为他这个结果能引出自由意志。但是如果你接受了他这个理论,那就有很多物理过程是真随机了。下面两个链接是两篇反对他的文章。认为是不是有完全不受影响的随机过程存不存在还不好说。上面基本上就是对这个问题比较前沿的讨论了。如果要答案的话,那就是不知道咯。但是绝大多数人倾向于相信量子过程是真随机。最高票答案对于量子过程是真随机可能有点过于肯定了吧。Bell's theorem大概相当于堵死了一条(最主要的)路,但也不能完全确定量子现象是真随机吧。,碼農赞同天哪,樓上的好像都不知道一件事情:隨機的意思不是「事件的發生我們永遠無法知曉,但是概率是知道的」,而是「我不知道裡面發生了什麼,但是這幾種情況發生的頻率正好就是這麼多,姑且能用」!如果没理解其中的差别,也就無法理解「」。我承認,不確定性原理除外;這個東西我學過「現代物理」並拿了A也沒能完全理解,我去問問物理老師。,公共图书馆打杂人员赞同我认为没有真正的随机,随机只是微观世界量子运动规律的宏表征说量子运动是无规律的,其实我觉得是因为量子运动的观察对象太细微,目前还不能实际掌握出规律来我深信量子运动的规律是一定有的,不管科学大牛们怎么说量子运动是上帝之手,、知乎用户赞同不少人引证量子力学说明真随机的存在,但爱因斯坦也不会是笨蛋,这么多人能看明白的事,他难道不明白?或许所谓量子力学的随机,只是限于人类现在的科技水平所获得错误认知。,从唯物掠过唯心,落于……无我。赞同我认为,所谓量子不确定性,只是一个表象,不能作为真随机存在的理由。观察会影响结果,人类永远无法掌握其规律,也许是正确的。但这并不等于它就真的没规律!!换句话说,如果量子现象的实质是微观文明,并且它们拥有真正的自由意志,那么,世界就是真随机的。或者,人类(或者存在别的生命)本身的意识,如果是不依赖肉体却可以随机干涉肉体的独立存在,那世界也是真随机的。总而言之,唯物论如果正确,世界就是伪随机的!知乎用户,道不同不相为谋。有.凡是都要和周围联系起来才对.你故意拿三个一样的球让人选,那每个都是随机了.也就是条件的限制.类推.下面是理论的推断--------------------------------------------------------------------------------------伪随机数的确并不随机,所以叫伪随机数.如果'宇宙中一切事件的发生都有个引发它的原因'是前提,要得到'整个宇宙不存在真正的随机事件'这个结论,就需要证明:随机事件=没有原因引发,而产生的事件.over.,改变世界只有一个随机事件,就是宇宙的起源。有了起源,以后就全部是固定的,有规律的。知乎用户思想也是物质的,艺术家(chaos)是指确定性因对初值敏感而表现出的不可预测的、类似的。匿名用户赞同对于一个有自由意志的个体,就存在完全随机。比如我要穿鞋前,请God(no offence)来猜我先哪只脚,他也不能打保票。,在知乎到处乱窜,什么都想搀和一手.......、知乎用户、 当你扔出硬币的时候,假如你知道所有能影响其结果的因素,知道所有影响其结果的物理定律,我们就能计算出最后落地的时候是正面还是反面。比如我们知道角动量,风速,硬币质量,重力加速度。。。我们就能通过这些数字来计算最后落地的结果。所以我们可以说,没有真正的随机。推而广之,假设我们能够了解所有的物理规律,那是不是我从宇宙诞生之时,就能计算出以后亿万年的发展结果?那是不是意思就是所有的一切都是早就注定好的?比如我现在发这个帖子其实在一亿年前就已经注定了的。 或者是其实我一个小时后我在思考什么其实现在已经注定好了。。。。但是这样是不是太荒谬了?我们一个小时后的思考,应该是一个随机的的,所以应该存在真正的随机啊。-------引自《天涯社区》 ,不必吝啬感谢但请分清你点的是赞还是赞同 人生是个大随机事件吗?那不是无数个小随机事件重叠导致的么?,互联网社区其实整个世界都有一定的随机性。。比如马哲里说的必然性和偶然性,偶然性就是一定程度上的随机性像微观世界中的电子运动,也是随机运动,我们只能知道电子在某一能量轨道上出现的概率是多少,但无法知道其某一时间的特定位置。光子的运动按照波粒二象性的说法,也是随机运动。当然,这些随机事件都是有一定概率下的随机时间,只能说有多大的把握出现某个事件,却不可能是定值,至少在现有科学水平下还是随机的。另外关于人的行为,心理学和哲学中都存在自由意志的概念,其大概意思就是说人有自由决定自己行为的能力。在一定程度上是随机的。这个世界有很多的不确定性。但也有符合某些规律的必然性。概率问题。。。
发表评论:
TA的最新馆藏[转]&[转]&[转]&[转]&[转]&[转]&}

我要回帖

更多关于 php 真随机数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信