使用C#的随机数

时间:2010-02-14 16:41:29

标签: c# random

我正在考虑生成1到5百万之间的随机数。这个过程不一定要快(虽然它会很好),但它必须尽可能随机(我知道什么都不是随机的)。我有种子的各种数据源。

我不确定.NET Random课程是否足够好。

这将用于选择中奖彩票。

8 个答案:

答案 0 :(得分:17)

System.Random课程可能已经足够了:

  

从一组有限的数字中以相等的概率选择伪随机数。所选择的数字不是完全随机的,因为使用确定的数学算法来选择它们,但是出于实际目的它们是足够随机的。 Random类的当前实现基于Donald E. Knuth的减法随机数生成器算法。有关更多信息,请参阅D. E. Knuth。 “计算机编程的艺术,第2卷:半数值算法”。 Addison-Wesley,Reading,MA,第二版,1981年。

您唯一需要注意的是,您不会经常重复使用相同的种子:

  

如果重复使用相同的种子,则会生成相同的数字序列。产生不同序列的一种方法是使种子值与时间相关,从而与每个新的Random实例产生不同的序列。

答案 1 :(得分:7)

如果您需要加密随机数,请使用System.Security.Cryptography.RNGCryptoServiceProvider类或使用RandomNumberGenerator.Create()工厂方法创建默认配置的随机数生成器。

答案 2 :(得分:5)

请参阅Jon Skeet的博文Revisiting Randomness,了解如何使用随机性:

  

重新审视随机性
几乎每个Stack Overflow都有问题   包括“随机”和“   “重复”有相同的基本答案。   这是最常见的“陷阱”之一   在.NET,Java中,毫无疑问是其他的   平台:创建一个新的随机   数字生成器没有指定   种子将取决于当前   瞬间。当前时间为   由电脑测量不   与如何相比经常变化   通常你可以随意创建和使用   数字生成器 - 所以代码   反复创建一个新的实例   随机并使用它一次将结束   显示了很多重复。

     

more...

答案 3 :(得分:5)

实际上,我最近在不同类型的PRNG上阅读了一篇非常好的文章,以及它们在几种不同的随机性测试方面的表现。不幸的是,我现在似乎无法找到它。然而,它的要点是,几乎所有流行编程语言中的默认随机数生成器都非常天真,并且具有相当大的偏差。

另一个答案已经提到,无论算法多么复杂,对于加密应用程序来说,根本没有PRNG。这是真的。既然你提到这将用于“选择中奖票”,那么我们暂时忽略它。

.NET System.Random类使用的Knuth算法主要针对速度而非随机分布进行优化。对于许多目的而言,它是“随机的”,大多数应用程序从不偏离太远,但在(a)游戏和(b)统计模拟领域,大多数人似乎认为这是一个糟糕的选择。它比以前在旧库中默认的LCG更好,但你仍然不想将它用于乐透之类的东西。

不要误以为你只是使用加密源。加密RNG的问题在于它们填充了一个字节流,但是将它转换为 x y 之间的单个随机整数需要你进行一些模运算(或舍入) - 两种方式相同的结果)。如果你的随机范围没有完全均匀地划分为由字节长度定义的2的幂,那么你将最终得到较低数字的偏差。生成的数据具有高熵,但您的结果将有偏差。

举一个简单的例子,让我们说你从1到10得到一个“完美”的随机数,现在你想把它变成1到7之间的随机数。你怎么做?简单地计算result % 7将严重偏向数字1-3。在使用加密RNG时,有一些方法可以减少偏差,但我想说的是加密RNG是专为加密应用而设计的,而使用其中一个用于蒙特卡罗模拟通常不是最好的想法。

据我所知,目前在游戏应用中常用的最受欢迎的“好”PRNG是Mersenne Twister。有一个.NET implementation here。该算法将所有Diehard Tests传递给随机分布;当您使用随机数进行概率和统计应用时,它几乎没有偏差,是一个不错的选择。

GNU科学图书馆也有一些RNG algorithms,毫不奇怪,Mersenne Twister位居榜首。不过,有些其他人值得关注好奇心。 RANLUX在死硬测试IIRC上也得分很高。

当然,埃里克对他的评论是正确的;如果您对随机数字的“随机性”没有具体的技术要求,那么所有这些信息都是徒劳的。我使用的定义适用于影响力相对较小的赌博/博彩应用程序(即不是每天有数百万访问者的主要注册赌博网站 - 对这些网站的随机性有更严格的规定)。

答案 4 :(得分:4)

要生成随机数,请创建Random类的对象,然后使用此对象的Next函数生成随机数。它有很多重载,如:

Next(int minimum, int maximum);
Next(int Maximum);

您可以在其中指定随机数之间的最小和最大范围。

代码段:

Random random = new Random();
int maxValue = 100;

int r = random.Next(maxValue);

答案 5 :(得分:3)

System.Random类非常有问题,并且不符合要求。从理论上讲,它应该提供比许多其他伪随机发生器更好的结果。它是第二版“C中的数字配方”第283页提供的Lagged Fibonacci Generator(LFG)的示例C代码的直接和字面端口(该代码在以后的版本中重写)。 LFG使用比其他许多库(例如Java)使用的线性同余生成器(LCG)更好的算法。

不幸的是,微软的System.Random类的实现有一个错误。有关详细信息,请参阅http://connect.microsoft.com/VisualStudio/feedback/details/634761/system-random-serious-bug。当打算输入'31'时,似乎有人意外输入'21'。这会破坏算法的伪随机特性。该链接包括来自MS的解释,说明为什么他们觉得在此阶段无法修复错误。

答案 6 :(得分:1)

如果您正在寻找真正的随机数,那么您应该考虑使用使用自然现象的在线随机数生成器,例如使用大气噪声的http://www.random.org。真随机数也为伪随机数生成器提供了良好的种子。

Sipwiz在答案中展示了如何在C#中使用它:Generate random values in C#。这也在这里讨论:http://www.vcskicks.com/random-number-generator.php

随机数生成器有很多角度。一个有趣的替代实现是ISSAC(ttp://burtleburtle.net/bob/rand/isaac.html),它也包含对偏见等的良好讨论,并且还有一个C#版本(http://burtleburtle.net/bob/rand/isaacafa.html)。

答案 7 :(得分:0)

.NET的Random应该没问题:

var random = new Random(System.DateTime.Now.Millisecond);

int randomNumber = random.Next(1, 5000000);