如何使用 C# 生成真正(非伪)随机数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1234094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:01:01  来源:igfitidea点击:

How can I generate truly (not pseudo) random numbers with C#?

c#algorithmmath

提问by Max

I know that the Random class can generate pseudo-random numbers but is there a way to generate truly random numbers?

我知道 Random 类可以生成伪随机数,但有没有办法生成真正的随机数?

采纳答案by Noldorin

The answer here has two main sides to it. There are some quite important subtleties to which you should pay due attention...

这里的答案有两个主要方面。有一些非常重要的微妙之处,你应该注意......

The Easy Way (for simplicity & practicality)

简单的方法(为了简单和实用)

The RNGCryptoServiceProvider, which is part of the Crypto API in the BCL, should do the job for you. It's still technically a pseudo-random number generated, but the quality of "randomness" is much higher - suitable for cryptographic purposes, as the name might suggest.

RNGCryptoServiceProvider,这是在BCL的加密API的一部分,应该为你做的工作。从技术上讲,它仍然是生成的伪随机数,但“随机性”的质量要高得多 - 顾名思义,适用于加密目的。

There are other crypographic APIs with high quality pseudo random generaters available too. Algorithms such as the Mersenne twisterare quite popular.

还有其他具有高质量伪随机生成器的密码 API。诸如梅森扭曲器之类的算法非常流行。

Comparing this to the Randomclass in the BCL, it is significantly better. If you plot the numbers generated by Randomon a graph, for example, you should be able to recognise patterns, which is a strong sign of weakness. This is largely due to the fact that the algorithm simply uses a seeded lookup table of fixed size.

RandomBCL 中的类相比,它要好得多。Random例如,如果您在图表上绘制由 生成的数字,您应该能够识别模式,这是弱点的强烈迹象。这主要是因为该算法仅使用固定大小的种子查找表。

The Hard Way (for high quality theoretical randomness)

The Hard Way(对于高质量的理论随机性)

To generate trulyrandom numbers, you need to make use of some natural phenomenon, such as nuclear decay, microscopic temperature fluctuations (CPU temperature is a comparatively conveient source), to name a few. This however is much more difficult and requires additional hardware, of course. I suspect the practical solution (RNGCryptoServiceProvideror such) should do the job perfectly well for you.

要生成真正的随机数,需要利用一些自然现象,例如核衰变、微观温度波动(CPU 温度是一个比较方便的来源)等等。然而,这当然要困难得多,并且需要额外的硬件。我怀疑实用的解决方案(RNGCryptoServiceProvider或类似的)应该非常适合您。

Now, note that if you really do require truly random numbers, you could use a service such as Random.org, which generates numbers with very high randomness/entropy (based on atmospheric noise). Data is freely available for download. This may nonetheless be unnecessarily complicated for your situation, although it certainly gives you data suitable for scientific study and whatnot.

现在,请注意,如果您确实需要真正的随机数,则可以使用诸如Random.org 之类的服务,它会生成具有非常高随机性/熵的数字(基于大气噪声)。数据可免费下载。尽管如此,这对于您的情况可能会不必要地复杂化,尽管它确实为您提供了适合科学研究之类的数据。

The choice is yours in the end, but at least you should now be able to make an informative decision, being aware of the various types and levels of RNGs.

最终选择权在您手中,但至少您现在应该能够做出信息丰富的决定,了解 RNG 的各种类型和级别。

回答by Mike Dinescu

short answer: It is not directly possible to generate TRULY RANDOM NUMBERSusing only C# (i.e. using only a purely mathematical construction).

简短回答:仅使用 C#(即仅使用纯数学结构)无法直接生成真正的随机数。

long(er) answer: Only by means of employing an external device capable of generating "randomness" such as a white noise generator or similar- and capturing the output of that device as a seed for a pseudo random number generator (PRG). That part could be accomplished using C#.

长(er)答案:只能通过采用能够产生“随机性”的外部设备(例如白噪声发生器或类似设备)并捕获该设备的输出作为伪随机数发生器(PRG)的种子。这部分可以使用 C# 来完成。

回答by Joseph Mansfield

True random numbers can only be generated if there is a truly random physical input device that provides the seed for the random function.

只有当存在真正随机的物理输入设备为随机函数提供种子时,才能生成真正的随机数。

Whether anything physical and truly random exists is still debated (and likely will be for a long time) by the science community.

科学界仍在争论(并且可能会持续很长时间)是否存在任何物理和真正随机的东西。

Psuedo-random number generators are the next best thing and the best are very difficult to predict.

伪随机数生成器是次优的,而最好的生成器很难预测。

回答by Paul Sasik

There is no way to generate truly random numbers with a computer. True randomness requires an external source that monitors some natural phenomenon.

没有办法用计算机生成真正的随机数。真正的随机性需要一个外部源来监控一些自然现象。

That said, if you don't have access to such a source of truly random numbers you could use a "poor man's" process like this:

也就是说,如果您无法访问这种真正随机数的来源,您可以使用这样的“穷人”流程:

  • Create a long array (10000 or more items?) of numbers
  • Populate the array with current time-seeded random numbers the standard way
  • When a random number is required, generate a random index into the array and return the number contained at that position
  • Create a new, current time-seeded random number at the array index to replace the number used
  • 创建一个长数组(10000 个或更多项目?)
  • 以标准方式用当前时间种子随机数填充数组
  • 当需要随机数时,在数组中生成一个随机索引并返回该位置包含的数字
  • 在数组索引处创建一个新的当前时间种子随机数以替换使用的数字

This two-step process should improve the randomness of your results somewhat without the need for external input.

这个两步过程应该在不需要外部输入的情况下稍微提高结果的随机性。

Here's a sample library that implements the above-described algorithm in C++: http://www.boost.org/doc/libs/1_39_0/libs/random/random-generators.html

这是在 C++ 中实现上述算法的示例库:http: //www.boost.org/doc/libs/1_39_0/libs/random/random-generators.html

回答by Kelly Gendron

I was debating building a random number generator based off twitter or one of the other social networking sites. Basically use the api to pull recent posts and then use that to seed a high quality pseudo random number generator. It probably isn't any more effective than randomizing off the timer but seemed like fun. Besides it seems like the best use for most of the stuff people post to twitter.

我正在讨论基于 Twitter 或其他社交网站之一构建随机数生成器。基本上使用 api 来提取最近的帖子,然后使用它来播种高质量的伪随机数生成器。它可能并不比随机化计时器更有效,但看起来很有趣。此外,它似乎是人们发布到 twitter 的大多数内容的最佳用途。

回答by High Performance Mark

As John von Neumann joked, "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin."

正如约翰·冯·诺依曼 (John von Neumann) 开玩笑说的那样:“任何考虑使用算术方法生成随机数字的人,当然都处于罪恶状态。”

回答by Moose

I always liked this idea, for the retro 60s look:

我一直很喜欢这个想法,对于 60 年代的复古外观:

Lavarand

拉瓦兰

回答by Jason S

Take a look at using an algorithm like Yarrowor Fortunawith entropy accumulation. The point with these algorithms is that they keep track of entropy as a measure of theoretical information content available for predicting future numbers by knowing the past numbers and the algorithms used to produce them; and they use cryptographic techniques to fold new entropy sources into the number generator.

看看使用像YarrowFortuna这样的算法进行熵积累。这些算法的重点在于,它们通过了解过去的数字和用于生成它们的算法来跟踪熵,作为可用于预测未来数字的理论信息内容的度量;他们使用密码技术将新的熵源折叠到数字生成器中。

You'll still need an external source of random data (e.g. hardware source of random numbers), whether that's time of keystrokes, or mouse movement, or hard disk access times, or CPU temperature, or webcam data, or stock prices, or whatever -- but in any case, you keep mixing this information into the entropy pools, so that even if the truly random data is slow or low quality, it's enough to keep things going in an unpredictable fashion.

您仍然需要随机数据的外部来源(例如随机数的硬件来源),无论是击键时间、鼠标移动时间、硬盘访问时间、CPU 温度、网络摄像头数据、股票价格或其他任何信息-- 但无论如何,你不断地将这些信息混合到熵池中,这样即使真正的随机数据很慢或质量很低,也足以让事情以不可预测的方式进行。

回答by user169551

There is no "true" random in computers, everything is based on something else. For some (feasible) ways to generate pseudorandom data, try something such as a pool of the HD temp, CPU temp, network usage (packets/second) and possibly hits/second to the webserver.

计算机中没有“真正的”随机,一切都基于别的东西。对于某些(可行的)生成伪随机数据的方法,请尝试诸如 HD 临时池、CPU 临时池、网络使用率(数据包/秒)和可能的网络服务器命中率/秒之类的方法。

回答by Ionic? Biz?u

This code will return you a random number between minand max:

此代码将返回一个介于min和之间的随机数max

private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public int RandomNumber(int min, int max)
{
    lock (syncLock)
    { // synchronize
        return random.Next(min, max);
    }
}

Usage:

用法:

int randomNumber = RandomNumber(0, 10); // a random number between 1 and 10