运行时如何生成随机数?

发布于 2024-10-07 09:53:00 字数 110 浏览 0 评论 0原文

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

Random.Next()

里面发生了什么?

Since computers cannot pick random numbers(can they?) how is this random number actually generated. For example in C# we say,

Random.Next()

What happens inside?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

饮湿 2024-10-14 09:53:01

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

You may checkout this article. According to the documentation the specific implementation used in .NET is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981.

千と千尋 2024-10-14 09:53:01

因为计算机无法选择随机数(可以吗?)

正如其他人所指出的,“随机”实际上是伪随机的。回答你的附加问题:是的,计算机可以选择真正随机的数字。这样做比伪随机数生成器的简单整数运算要昂贵得多,并且通常不需要。然而,在某些应用中,您必须具有不可预测的真实随机性:立即想到密码学和在线扑克。如果使用可预测的伪随机源,那么攻击者就可以更轻松地解密/伪造消息,而作弊者可以弄清楚谁手里有什么。

.NET 加密类具有提供适合的随机数的方法密码学或需要金钱的游戏。至于它们是如何工作的:关于加密强度随机性的文献非常广泛;有关详细信息,请参阅任何优秀的大学密码学本科教科书。

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

Since computers cannot pick random numbers (can they?)

As others have noted, "Random" is actually pseudo-random. To answer your parenthetical question: yes, computers can pick truly random numbers. Doing so is much more expensive than the simple integer arithmetic of a pseudo-random number generator, and usually not required. However there are applications where you must have non-predictable true randomness: cryptography and online poker immediately come to mind. If either use a predictable source of pseudo-randomness then attackers can decrypt/forge messages much more easily, and cheaters can figure out who has what in their hands.

The .NET crypto classes have methods that give random numbers suitable for cryptography or games where money is on the line. As for how they work: the literature on crypto-strength randomness is extensive; consult any good university undergrad textbook on cryptography for details.

Specialty hardware also exists to get random bits. If you need random numbers that are drawn from atmospheric noise, see www.random.org.

青巷忧颜 2024-10-14 09:53:01

高德纳 (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 ^ 兰特2() ...
v2 = rand2() >>> 8 ^ rand5() ..

并想象种子并不总是前进。现在你开始制作一些基于逆向工程更难以预测的东西,并且序列更长。

例如,如果每次计算 rand1(),但仅每 3 次将 rand2() 中的种子提前,则组合它们的生成器的重复时间可能不会比任一周期长得多。

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

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

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

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

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

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

Knuth covers the topic of randomness very well.

We don't really understand random well. How can something predictable be random? And yet pseudo-random sequences can appear to be perfectly random by statistical tests.

There are three categories of Random generators, amplifying on the comment above.

First, you have pseudo random number generators where if you know the current random number, it's easy to compute the next one. This makes it easy to reverse engineer other numbers if you find out a few.

Then, there are cryptographic algorithms that make this much harder. I believe they still are pseudo random sequences (contrary to what the comment above implies), but with the very important property that knowing a few numbers in the sequence does NOT make it obvious how to compute the rest. The way it works is that crypto routines tend to hash up the number, so that if one bit changes, every bit is equally likely to change as a result.

Consider a simple modulo generator (similar to some implementations in C rand() )

int rand() {
return seed = seed * m + a;
}

if m=0 and a=0, this is a lousy generator with period 1: 0, 0, 0, 0, ....
if m=1 and a=1, it's also not very random looking: 0, 1, 2, 3, 4, 5, 6, ...

But if you pick m and a to be prime numbers around 2^16, this will jump around nicely looking very random if you are casually inspecting. But because both numbers are odd, you would see that the low bit would toggle, ie the number is alternately odd and even. Not a great random number generator. And since there are only 2^32 values in a 32 bit number, by definition after 2^32 iterations at most, you will repeat the sequence again, making it obvious that the generator is NOT random.

If you think of the middle bits as nice and scrambled, while the lower ones aren't as random, then you can construct a better random number generator out of a few of these, with the various bits XORed together so that all the bits are covered well. Something like:

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

Still, every number is flipping in synch, which makes this predictable. And if you get two sequential values they are correlated, so that if you plot them you will get lines on your screen. Now imagine you have rules combining the generators, so that sequential values are not the next ones.
For example

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

and imagine that the seeds don't always advance. Now you're starting to make something that's much harder to predict based on reverse engineering, and the sequence is longer.

For example, if you compute rand1() every time, but only advance the seed in rand2() every 3rd time, a generator combining them might not repeat for far longer than the period of either one.

Now imagine that you pump your (fairly predictable) modulo-type random number generator through DES or some other encryption algorithm. That will scramble up the bits.

Obviously, there are better algorithms, but this gives you an idea. Numerical Recipes has a lot of algorithms implemented in code and explained. One very good trick: generate not one but a block of random values in a table. Then use an independent random number generator to pick one of the generated numbers, generate a new one and replace it. This breaks up any correlation between adjacent pairs of numbers.

The third category is actual hardware-based random number generators, for example based on atmospheric noise

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

This is, according to current science, truly random. Perhaps someday we will discover that it obeys some underlying rule, but currently, we cannot predict these values, and they are "truly" random as far as we are concerned.

The boost library has excellent C++ implementations of Fibonacci generators, the reigning kings of pseudo-random sequences if you want to see some source code.

旧竹 2024-10-14 09:53:01

我只是为问题的第一部分(“他们可以吗?”部分)添加一个答案。h

计算机可以生成(嗯,生成可能不是一个完全准确的词)随机数(如,不是伪随机数)。具体来说,通过使用通过专用硬件设备(例如,基于噪声生成随机性)获得的环境随机性或通过使用环境输入(例如硬盘定时、用户输入事件定时)。

但是,这与第二个问题(即 Random.Next() 的工作原理)无关。

I'll just add an answer to the first part of the question (the "can they?" part).h

Computers can generate (well, generate may not be an entirely accurate word) random numbers (as in, not pseudo-random). Specifically, by using environmental randomness which is gotten through specialized hardware devices (that generates randomness based on noise, for e.g.) or by using environmental inputs (e.g. hard disk timings, user input event timings).

However, that has no bearing on the second question (which was how Random.Next() works).

不乱于心 2024-10-14 09:53:01

Random 类是一个伪随机数生成器

它基本上是一个极长但确定性的重复序列。 “随机性”来自于从不同的位置开始。指定从哪里开始是通过为随机数生成器选择 种子 来完成的,例如可以这样做通过使用系统时间或从另一个随机源获取随机种子。 默认 Random 构造函数 使用系统时间作为种子。

用于生成数字序列的实际算法记录在 MSDN

Random 类的当前实现基于 Donald E. Knuth 的减法随机数生成器算法。欲了解更多信息,请参阅 DE Knuth。 “计算机编程艺术,第 2 卷:半数值算法”。 Addison-Wesley,雷丁,马萨诸塞州,第二版,1981 年。

The Random class is a pseudo-random number generator.

It is basically an extremely long but deterministic repeating sequence. The "randomness" comes from starting at different positions. Specifying where to start is done by choosing a seed for the random number generator and can for example be done by using the system time or by getting a random seed from another random source. The default Random constructor uses the system time as a seed.

The actual algorithm used to generate the sequence of numbers is documented in MSDN:

The current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981.

小兔几 2024-10-14 09:53:01

计算机使用伪随机数生成器。本质上,它们的工作原理是从种子数开始,并在每次需要新的伪随机数时通过算法对其进行迭代。

该过程当然是完全确定性的,因此给定的种子每次使用时都会生成完全相同的数字序列,但生成的数字形成统计上均匀的分布(近似),这很好,因为在大多数情况下,您都可以需求是随机的随机性。

通常的做法是使用当前系统时间作为种子,但如果需要更高的安全性,可以从物理源(例如磁盘延迟)收集“熵”,以便生成更难以预测的种子。在这种情况下,您还需要使用加密强度高的随机数生成器,例如

Computers use pseudorandom number generators. Essentially, they work by start with a seed number and iterating it through an algorithm each time a new pseudorandom number is required.

The process is of course entirely deterministic, so a given seed will generate exactly the same sequence of numbers every time it is used, but the numbers generated form a statistically uniform distribution (approximately), and this is fine, since in most scenarios all you need is stochastic randomness.

The usual practice is to use the current system time as a seed, though if more security is required, "entropy" may be gathered from a physical source such as disk latency in order to generate a seed that is more difficult to predict. In this case, you'd also want to use a cryptographically strong random number generator such as this.

对你而言 2024-10-14 09:53:01

我不知道太多细节,但我知道的是,使用种子来生成随机数,然后基于某种使用该种子获得新数字的算法。

如果你得到基于相同种子的随机数,它们通常是相同的。

I don't know much details but what I know is that a seed is used in order to generate the random numbers it is then based on some algorithm that uses that seed that a new number is obtained.

If you get random numbers based on the same seed they will be the same often.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文