如何在运行时生成随机数?

nav*_*een 12 c# random algorithm programming-languages

由于计算机无法选择随机数(可以吗?)这个随机数是如何实际生成的.例如在C#中我们说,

Random.Next()
Run Code Online (Sandbox Code Playgroud)

里面发生了什么?

Dar*_*rov 14

你可以查看这篇文章.根据文档,.NET中使用的具体实现基于Donald E. Knuth的减法随机数生成器算法.有关更多信息,请参阅DE Knuth."计算机编程的艺术,第2卷:半数值算法".Addison-Wesley,Reading,MA,第二版,1981.


Eri*_*ert 6

由于计算机无法选择随机数(可以吗?)

正如其他人所说,"随机"实际上是伪随机的.回答你的括号问题:是的,计算机可以选择真正随机的数字.这样做比伪随机数发生器的简单整数算法昂贵得多,并且通常不需要.但是,有些应用程序必须具有不可预测的真正随机性:立即想到加密和在线扑克.如果要么使用可预测的伪随机源,那么攻击者可以更容易地解密/伪造消息,并且骗子可以找出谁拥有他们手中的东西.

.NET加密类的方法可以为随机数提供适合加密或游戏的随机数字.至于它们如何工作:关于加密随机性的文献是广泛的; 有关详细信息,请参阅任何优秀的大学本科密码学教科书.

还存在专用硬件以获得随机位.如果您需要从大气噪声中提取的随机数,请访问www.random.org.

  • 所有基于计算机/逻辑的RNG都是伪随机*,除非*它们具有真正的随机源.随机源可能是放射性衰变.一些计算机硬件具有随机数发生器,其具有处于不稳定状态的晶体管并且产生恒定的随机比特流.伪随机和随机之间的区别是伪随机是确定性的,但是从很多来源拉取数据是非常难以预测的,即使你知道所有的来源,真正的随机,你仍然无法知道输出,直到它发生. (2认同)

Dov*_*Dov 5

Knuth 很好地涵盖了随机性主题。

我们不太了解随机。可预测的东西怎么可能是随机的?然而,通过统计测试,伪随机序列似乎是完全随机的。

随机生成器分为三类,放大了上面的评论。

首先,你有伪随机数生成器,如果你知道当前的随机数,就很容易计算下一个。如果您发现一些数字,这可以轻松地对其他数字进行逆向工程。

然后,有密码算法使这变得更加困难。我相信它们仍然是伪随机序列(与上面的评论所暗示的相反),但是具有非常重要的特性,即知道序列中的一些数字并不能使如何计算其余数字变得显而易见。它的工作方式是加密例程倾向于对数字进行散列,因此如果一位发生变化,那么每一位都同样有可能因此而发生变化。

考虑一个简单的模生成器(类似于 C rand() 中的一些实现)

int rand() { 返回种子 = 种子 * m + a; }

如果 m=0 和 a=0,这是一个糟糕的生成器,周期为 1: 0, 0, 0, 0, .... 如果 m=1 和 a=1,它看起来也不是很随机:0, 1, 2, 3, 4, 5, 6, ...

但是,如果您选择 m 和 a 作为 2^16 左右的质数,那么如果您随意检查,这将看起来非常随机。但是因为两个数字都是奇数,您会看到低位会切换,即数字交替出现奇数和偶数。不是一个很好的随机数生成器。并且由于在 32 位数字中只有 2^32 个值,根据定义,最多在 2^32 次迭代之后,您将再次重复该序列,从而很明显生成器不是随机的。

如果您认为中间的位很好且乱码,而较低的位不那么随机,那么您可以从其中的一些位中构建一个更好的随机数生成器,将各个位异或在一起,以便所有位都是覆盖得很好。就像是:

(rand1() >> 8) ^ rand2() ^ (rand3() > 5) ...

尽管如此,每个数字都在同步翻转,这使得这可以预测。如果你得到两个连续的值,它们是相关的,所以如果你绘制它们,你会在屏幕上看到线条。现在假设您有组合生成器的规则,因此顺序值不是下一个。例如

v1 = rand1() >> 8 ^ rand2() ... v2 = rand2() >> 8 ^ rand5() ..

并想象种子并不总是前进。现在你开始做一些基于逆向工程更难预测的事情,而且序列更长。

例如,如果您每次都计算 rand1(),但每 3 次只在 rand2() 中推进种子,则组合它们的生成器的重复时间可能不会长于任一周期。

现在想象一下,您通过 DES 或其他一些加密算法抽取您的(相当可预测的)模类型随机数生成器。这将打乱位。

显然,有更好的算法,但这给了你一个想法。Numerical Recipes 在代码中实现了许多算法并进行了解释。一个非常好的技巧:在表格中生成的不是一个而是一组随机值。然后使用独立的随机数生成器从生成的数字中选取一个,生成一个新的并替换它。这打破了相邻数字对之间的任何相关性。

第三类是实际的基于硬件的随机数发生器,例如基于大气噪声

http://www.random.org/randomness/

根据目前的科学,这是真正随机的。也许有一天我们会发现它遵循一些潜在的规则,但目前,我们无法预测这些值,就我们而言,它们是“真正”随机的。

boost 库具有斐波那契生成器的优秀 C++ 实现,如果您想查看一些源代码,它是伪随机序列的统治者。