婚戒大概多少钱:真随机数的定义是什么

来源:百度文库 编辑:高考问答 时间:2024/04/30 10:08:27

从软件的角度来说,如果是计算机起卦,则要用到随机数,而电脑中的随机数是假的随机数,搞那么多年程序,我还没看到过什么玩意能够有真随机数,按现代科学定义的真随机数的产生条件有起码两个:
1、真随机数数列是不可预计的,因而也不可能重复产生两个相同的真随机数数列。
2、真随机数只能用某些随机物理过程来产生。例如:放射性衰变、电子设备的热噪音、宇宙射线的触发时间等等。
在计算机中,为了满足信息熵的特性,常常是用到的信息源包括用户的人为反应或某种经过排列变形后的高频时钟的序列或者是用户运动鼠标的路径的坐标等,这在一般的程序里据我看是很少触及到的。因此,计算机上的起卦方法先不谈真随机数的如何的处理问题,还有取到了数又该如何变化的问题。如果更深化的话,还需要要论及世界的本质之类的哲学命题,暂且不表。就目前起卦程序主要在网上起而言,关联于时间的起卦法也许还有可商议之处,而对随机要求性较强的起卦方法是很不适合的。

1. 如何产生一定范围内的随机数?

直接的方法是:

rand() % N;

返回从 0 到 N - 1 的数字。但这个方法不好,因为许多随机数发生器的低位比特并不随机。一个较好的方法是:

(int)((double)rand() / ((double)RAND_MAX + 1) * N);

如果你不希望使用 double,另一个方法是:

rand() / (RAND_MAX / N + 1);

两种方法都需要知道 RAND_MAX,而且假设 N 要远远小于 RAND_MAX。ANSI 规定标准头文件 stdlib.h 中包含 RAND_MAX 的 #define。顺便提一下,RAND_MAX 是个常数,它告诉你 C 库函数 rand() 的固定范围。你不可以设 RAND_MAX 为其它的值,也没有办法要求 rand() 返回其它范围的值。如果你用的随机数发生器返回的是 0 到 1 的浮点值,要取得范围在 0 到 N - 1 内的整数,只要将随机数乘以 N 就可以了。

2. 为什么每次执行程序,rand() 都返回相同顺序的数字?

你可以调用 srand() 来初始化伪随机数发生器的种子,传递给 srand() 的值应该是真正的随机数,例如当前时间:

#include <stdlib.h>
#include <time.h>
srand((unsigned int)time((time_t *)NULL));

请注意,在一个程序执行中多次调用 srand() 并不见得有帮助!不要为了取得“真随机数”而在每次调用 rand() 前都调用 srand()!

3. 我需要随机的真/假值,所以我用直接用 rand() % 2,可是我得到交替的 0, 1, 0, 1, 0 。

这是个低劣的伪随机数生成器,在低位比特中不随机!很不幸,某些系统就提供这样的伪随机数生成器。请试着使用高位比特,具体请参考本文第 1 点。

  随机数是专门的随机试验的结果。
  在统计学的不同技术中需要使用随机数,比如在从统计总体中抽取有代表性的样本的时候,或者在将实验动物分配到不同的试验组的过程中,或者在进行蒙特卡罗模拟法计算的时候等等。
  产生随机数有多种不同的方法。这些方法被称为随机数发生器。随机数最重要的特性是:它所产生的后面的那个数与前面的那个数毫无关系。
  真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。
  在实际应用中往往使用伪随机数就足够了。这些数列是“似乎”随机的数,实际上它们是通过一个固定的、可以重复的计算方法产生的。计算机或计算器产生的随机数有很长的周期性。它们不真正地随机,因为它们实际上是可以计算出来的,但是它们具有类似于随机数的统计特征。这样的发生器叫做伪随机数发生器。
  在真正关键性的应用中,比如在密码学中,人们一般使用真正的随机数。

真随机数一般都是相对于数组而言,真随机数就是没有规律的数,你不能预见其下一个数值是多少,真随机数是个诡异的东西,一个源于物理现象得到的真随机数组一经公开就不再是真随机数组了,因为得到数组的人都可以知道下一个数是什么。
  以往大家有个共识,就是计算机不能产生真随机数,其实这是对计算机认识不够造成的,计算机有多种产生随机数的方法,这里仅举一例:
  最常用的C语言中有些函数的特点是每次调用它执行时间不一样,也就是执行时间有一定的随机性,利用此特性我们可以得到所需要的随机数。这些函数有Beep(0,0),SetWindowText(NULL),MessageBeep(MB_ICONQUESTION)等,其它语言的函数也有类似情况是肯定的。
  我们只要连续调用此类函数,监测其执行时间,处理执行时间就可以达到目的。但函数的执行时间都是很短暂的,用一般测量时间的方法都太粗糙了,必须自己设计度量方法。每个计算机都有其工作频率称为主频,与之相对应的是时钟周期,做一个函数读取计算机运行以来的时钟周期,用函数运行时计算机所经历的周期数来度量时间;测量一下当前的周期数,让函数运行,再测量一下当前的周期数,两个周期数的差值再减去一个本底值就代表了函数运行时间,如此做多个循环就可以大量采集运行时间了,处理运行时间数组得到随机数组。
  且看实验数据:
  Beep(0,0)函数的运行时间115636,114283,114899,115030,114488,114350,114866,115132,114317,114757
  放在字数组里则有  50100,48747,49363,49494,48952,48814,49330,49596,48781,49221
  放在字节数组里则有 180,107,211,86,56,174,178,188,141,69
  显然放到16位的字数组里效果不好,这是因为函数运行时间只比16位的最大值大0.7倍左右。但放到8位数组里效果不错,而其它位数的数据由此组合即可。
  通过生成大量数据的检测还没有发现周期现象,也就是从不重复的,数组长度大时所有元素等概率出现随机性良好,所以它们是真随机数。
  这里展示了程序连续生成大随机数:http://clip2net.com/s/1Dphz

电子程序中的随机数其实并不随机,只是周期性非常长,可以用计算机算出来,只是因为计算量大要算很久可能算完了人家早就把密码换了甚至需要几百年来计算,但是假设你有一台超级牛逼的量子计算机就可以很快算出来的。
真随机数的意思就是说这个东西真的是随机的,无法预测,就算是量子计算机也没用。
中国的的反量子计算机加密就是真随机数,直接用双缝干涉实验得出的一个值。