简体   繁体   English

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

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

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

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. RNGCryptoServiceProvider是BCL中Crypto API的一部分,应该为您完成工作。 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. 它在技术上仍然是生成的伪随机数,但“随机性”的质量要高得多 - 适合加密目的,正如名称所暗示的那样。

There are other crypographic APIs with high quality pseudo random generaters available too. 还有其他具有高质量伪随机生成器的加密API。 Algorithms such as the Mersenne twister are quite popular. 诸如梅森捻线机之类的算法非常受欢迎。

Comparing this to the Random class in the BCL, it is significantly better. 将其与BCL中的Random类进行比较,效果明显更好。 If you plot the numbers generated by Random on a graph, for example, you should be able to recognise patterns, which is a strong sign of weakness. 例如,如果您在图表上绘制Random生成的数字,您应该能够识别模式,这是弱点的强烈迹象。 This is largely due to the fact that the algorithm simply uses a seeded lookup table of fixed size. 这主要是因为该算法仅使用固定大小的种子查找表。

The Hard Way (for high quality theoretical randomness) 艰难的道路(高质量的理论随机性)

To generate truly random 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. 要生成真正随机的数字,您需要利用一些自然现象,例如核衰变,微观温度波动(CPU温度是一个相对便利的来源),仅举几例。 This however is much more difficult and requires additional hardware, of course. 然而,这当然要困难得多,并且需要额外的硬件。 I suspect the practical solution ( RNGCryptoServiceProvider or such) should do the job perfectly well for you. 我怀疑实用的解决方案( 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 ). 现在,请注意,如果您确实需要真正随机的数字 ,则可以使用Random.org等服务,该服务生成具有非常高的随机性/熵(基于大气噪声 )的数字。 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. 尽管如此,这可能会使您的情况变得不必要地复杂化,尽管它确实为您提供了适合科学研究的数据等等。

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。

short answer: It is not directly possible to generate TRULY RANDOM NUMBERS using only C# (ie using only a purely mathematical construction). 简短回答:不能直接使用C#生成TRULY RANDOM NUMBERS (即仅使用纯粹的数学结构)。

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). 长(呃)答案:仅通过采用能够产生“随机性”的外部设备,例如白噪声发生器或类似设备,并将该设备的输出捕获为伪随机数发生器(PRG)的种子。 That part could be accomplished using C#. 那部分可以使用C#完成。

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. 伪随机数生成器是下一个最好的东西,最好的很难预测。

正如约翰·冯·诺伊曼开玩笑说的那样,“任何考虑产生随机数字的算术方法的人当然都处于犯罪状态。”

The thread is old and answered, but i thought I'd proceed anyway. 线程已经过时并且已经回答了,但我认为无论如何我都会继续。 It's for completeness and people should know some things about Random in c#. 这是为了完整性,人们应该在c#中了解一些关于Random的事情。

As for truly random, the best you can ever hope to do is use a "secure Pseudo Random Generator" like salsa20 or RC4 (sort of, sometimes). 至于真正随机的,你所希望做的最好的就是使用像salsa20或RC4这样的“安全伪随机生成器”(有时候是一种)。 They pass a barrage of tests where "efficient" adversaries try to distinguish them from random. 他们通过了一系列测试,“有效”的对手试图将它们与随机区分开来。 This comes with certain costs and is probably unnecessary for most uses. 这需要一定的成本,对于大多数用途来说可能是不必要的。

The random class in c# is pretty good most of the time, it has a statically distribution that looks random. c#中的随机类在大多数情况下非常好,它具有看起来随机的静态分布。 However the default seed for random() is the system time. 但是,random()的默认种子是系统时间。 So if you take lots of randoms at the "same time" they are taken with the same seed and will be the same ("random" is completely deterministic, don't let it fool you). 因此,如果你在“同一时间”采取大量的randoms,他们将使用相同的种子并将是相同的(“随机”是完全确定的,不要让它欺骗你)。 Similar system time seeds also may produce similar numbers because of random class's shortcomings. 由于随机类的缺点,类似的系统时间种子也可能产生类似的数字。 The way to deal with this is to set you own seeds, like 解决这个问题的方法是设置自己的种子,比如

Random random = new Random((int)DateTime.Now.Ticks & (0x0000FFFF + x));

where x is some value you increment if you've created a loop to get a bunch of random numbers, say. 其中x是你增加的一些值,如果你已经创建了一个循环来获取一堆随机数,比如说。

Also with c# random extensionsto your new variable like NextDouble() can be helpful in manipulating the random numbers, in this case crow-baring them into interval (0,1) to become unif(0,1), which happens is a distribution you can plug into stat formulas to create all the distributions in statistics. 另外用c#random extensionsto你的新变量如NextDouble()可以帮助你操作随机数,在这种情况下,将它们变成间隔(0,1)变成unif(0,1),这就是你的分布可以插入统计公式来创建统计中的所有分布。

Take a look at using an algorithm like Yarrow or Fortuna with entropy accumulation. 看看使用像YarrowFortuna这样的算法和熵累积。 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. 他们使用加密技术将新的熵源折叠到数字生成器中。

You'll still need an external source of random data (eg 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温度,网络摄像头数据,股票价格等等 - 但无论如何,你不断将这些信息混合到熵池中,这样即使真正的随机数据速度慢或质量低,也足以让事情以不可预测的方式进行。

This code will return you a random number between min and max : 此代码将返回minmax之间的随机数:

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

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 创建一个长数组(10000或更多项?)的数字
  • 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 在数组索引处创建一个新的当前时间种子随机数,以替换使用的数字

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

I was debating building a random number generator based off twitter or one of the other social networking sites. 我正在讨论基于twitter或其他社交网站建立一个随机数生成器。 Basically use the api to pull recent posts and then use that to seed a high quality pseudo random number generator. 基本上使用api来拉最近的帖子,然后使用它来播种高质量的伪随机数生成器。 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的最佳用途。

I always liked this idea, for the retro 60s look: 我总是喜欢这个想法,对于60年代的复古外观:

Lavarand Lavarand

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临时,网络使用(数据包/秒)以及可能到网络服务器的点击/秒等内容。

Just to clarify everyone saying that there is no True RNG available in C# or on your computer is mistaken. 只是为了澄清每个人都说C#或您的计算机上没有真正的RNG可用是错误的。 A multi-core processor is inherently a True RNG. 多核处理器本身就是真正的RNG。 Very simply by taking advantage of processor spin you can generate bools that have no discernible pattern. 非常简单地利用处理器旋转,您可以生成没有可辨别模式的bool。 From there you can generate whatever number range you want by using the bools as bits and constructing the number by adding the bits together. 从那里你可以使用bools作为位生成你想要的任何数字范围,并通过将位加在一起来构造数字。

Yes this is magnitudes slower than a purely mathematical solution but a purely mathematical solution will always have a pattern. 是的,这比纯粹的数学解决方案慢,但纯粹的数学解决方案总是有一个模式。

public static bool GenerateBoolean()
{
    var gen1 = 0;
    var gen2 = 0;
    Task.Run(() =>
    {
        while (gen1 < 1 || gen2 < 1)
            Interlocked.Increment(ref gen1);
    });
    while (gen1 < 1 || gen2 < 1)
        Interlocked.Increment(ref gen2);
    return (gen1 + gen2) % 2 == 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM