我正在考虑生成1到5百万之间的随机数。这个过程不一定要快(虽然它会很好),但它必须尽可能随机(我知道什么都不是随机的)。我有种子的各种数据源。
这将用于选择中奖彩票。
答案 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中,毫无疑问是其他的 平台:创建一个新的随机 数字生成器没有指定 种子将取决于当前 瞬间。当前时间为 由电脑测量不 与如何相比经常变化 通常你可以随意创建和使用 数字生成器 - 所以代码 反复创建一个新的实例 随机并使用它一次将结束 显示了很多重复。
答案 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);