Jav*_*ram 4 language-agnostic random
是否投掷硬币以获得随机位?
或者掷骰子以获得1到6的随机整数?
或者从洗牌的甲板上拿一张牌来获得1到52的数字?
.
.
.
或者它能像我们一样思考还是像我们一样拥有智慧?
显然,上述示例不能是生成随机数据的方法.
那么软件库如何random在给定范围内生成数字?
哪个更随机:人工或软件生成?
Joe*_*oey 11
(注意:我忽略了在你的问题中使用"编译器"一词,因为它实际上并不意味着什么.相反,这通常是关于计算中的随机[和伪随机]数字及其用途.)
你永远不能拥有确定性过程的真随机数,这就是为什么计算机不适合生成它们(因为CPU只能以确定的方式翻转位).大多数语言,框架和库使用所谓的伪随机数生成器(PRNG).那些采用种子,它是一种初始状态向量,可以是单个数字或数字数组,并从那里生成一系列看似随机的值.结果通常满足某些统计测量,但不是完全随机的,因为相同的种子将产生完全相同的序列.
最简单的PRNG之一是所谓的线性同余发生器(LCG).它只有一个数字作为状态(最初是种子).然后对于每个连续的返回值,公式如下所示:
LCG公式:x_(n + 1)=a⋅x_n+ b(modc)http://hypftier.de/dump/SO-6593636-lcg.png
其中a,b和c是发电机的常数.c通常是2的幂,例如2 32,因为它易于实现(自动完成)和快速.但是,找到a和b的良好值很难.作为一个最简单的例子,当使用a = 2和b = 0时,您可以看到结果值永远不会是奇数.这限制了发电机可以非常严重地产生的值的范围.一般来说,LCG是一个非常古老的概念,并且长期被更好的发电机取代,所以不要使用它们,除非在极其有限的环境中(尽管通常即使嵌入式系统也可以处理更好的发电机而没有问题) - MT19937或其概括,WELL对于那些根本不想担心伪随机数属性的人来说,生成器通常要好得多.
PRNG的一个主要应用是模拟.由于PRNG可以给出统计特性的估计或保证,并且由于种子的性质,实验可以完全重复,因此它们在这里做得很好.想象一下,您正在发表论文,并希望其他人复制您的结果.使用硬件RNG(如下所示),除了包含您使用的每个随机数之外,您没有其他选择.对于可以轻松使用数十亿或更多数字的蒙特卡罗模拟,这是不太可行的.
然后有用于加密应用程序的随机数生成器,例如用于保护SSL连接.这里的示例是Windows'CryptGenRandom或Unix /dev/urandom.那些通常也是 PRNG,但他们使用所谓的"熵池"进行播种,其中包含不可预测的值.这里的要点是产生不可预测的序列,即使相同的种子仍然会产生相同的序列.为了尽量减少攻击者猜测序列的影响,他们需要定期重新播种.熵池是从系统中的各个点收集的:事件,例如输入,网络活动等.有时它也被初始化,整个系统中的内存位置被假定为包含垃圾.但是,如果已经完成,必须注意确保熵池确实包含不可预测的内容.几年前Debian在OpenSSL中出错了.
您还可以使用熵池直接获取随机编号,(如linux的/dev/random,FreeBSD的,而不是使用相同的算法/dev/random为/dev/urandom),但你也不要太离谱了吧,一旦它是空的还需要一段时间来补充.这就是为什么上面提到的算法通常用于将小熵扩展到更大的体积.
然后是基于硬件的随机数发生器,它使用不可预测的自然过程,例如放射性衰减或电线中的电噪声.那些是需要许多"真正"随机数的最苛刻的应用程序,并且能够每秒产生几百MiB的随机性,通常(好吧,数据点是几年,但我怀疑它可以做多少现在更快).
你可以通过编写一个程序来模拟这样的事情,这个程序从带有镜头盖的网络摄像头开始(当时只剩下噪声)或者在没有实际输入的情况下从音频输入开始.这些是精细一小黑客,但通常不会产生良好的随机数,因为它们被偏置,即,在比特流中零和一不与相同的频率表示(或者,去进一步,所述序列00,01,10和11不以相同的频率生成...您也可以为更大的序列执行此操作.因此,实际硬件RNG的一部分用于确保结果值满足某些统计分布属性.
有些人实际上掷骰子以获得随机掷骰子甚至将其置于超速状态.人类制作非常糟糕的随机数生成器.