使用 System.Random
类可能已经足够好了:
伪随机数是从有限数字集中以等概率选择的。选择的数字并不完全随机,因为采用了确定的数学算法来选择它们,但对于实际目的来说它们已足够随机。当前的 Random 类实现基于 Donald E. Knuth 的差分随机数生成器算法。更多信息请参见 D. E. Knuth 所著《计算机程序设计艺术第二卷:半数值算法》(Addison-Wesley, Reading, MA, 第二版,1981 年)。
唯一需要注意的是不要太频繁地重复使用相同的种子:
如果反复使用相同的种子,则会生成相同的一系列数字。产生不同序列的一种方法是使种子值与时间相关,从而在每个新的 Random 实例中产生不同的序列。
System.Random
的特定错误版本上运行了一堆统计测试后,我并不清楚是否还有其他关于RNG应该更加令人担忧的问题。当然,它有几个不同的问题:https://github.com/dotnet/corefx/issues/23298 - fugledeSystem.Security.Cryptography.RNGCryptoServiceProvider
类或使用 RandomNumberGenerator.Create()
工厂方法创建默认配置的随机数生成器。System.Random
的又一个原因,因为它们的 Next(...)
实现存在偏差(它们似乎不使用 %
,但数字并不是等可能的)。 - CodesInChaosSystem.Random
不能用于加密数字,这正是我的答案所涉及的内容。 - Steven最近我读了一篇非常好的文章,介绍了不同类型的伪随机数生成器(PRNGs)在多个随机性测试中的表现。但很遗憾,我现在找不到它了。总的来说,几乎所有流行编程语言中默认的随机数生成器都很幼稚,具有相当大的偏差。
另一个答案已经提到,无论算法有多复杂,没有任何PRNG可以用于加密应用。这是正确的。既然你提到这将用于“选择获胜彩票”,那么我们暂且不考虑这个问题。
.NET System.Random
类使用的Knuth算法主要针对速度进行了优化,而不是随机分布。对于许多目的来说,它的随机性已经足够好了,大多数应用程序也没有离开这个范围。但在游戏和统计模拟领域,大多数人似乎认为它是一个糟糕的选择。它比旧库中默认的线性同余发生器(LCGs)更好,但你仍然不想将其用于类似于彩票之类的东西。
作为一个简单的例子,假设您从1到10中获得了一个“完美”的随机数,现在您想将其转换为介于1和7之间的随机数。怎么做?简单地计算result % 7
会严重偏向于数字1-3。使用加密随机数生成器时有一些减少偏差的方法,但我试图表达的观点是,加密随机数生成器是专为加密应用而设计的,而在蒙特卡罗模拟中使用其中之一通常不是最好的选择。
当然,Eric的评论是正确的;如果您不具有关于需要多么随机的特定技术要求,则所有这些信息都是无用的。我正在使用一个适用于相对低影响的赌博/游戏应用程序的定义(即不是每天有数百万访问者的主要注册赌博网站-这些网站对随机性有更严格的规定)。
要生成随机数,需创建一个Random
类的对象,然后使用该对象的Next
函数来生成随机数。它有许多重载,例如:
Next(int minimum, int maximum);
Next(int Maximum);
您可以指定要生成的随机数的最小和最大范围。
代码片段:
Random random = new Random();
int maxValue = 100;
int r = random.Next(maxValue);
int.MinValue
,则会被映射到int.MaxValue
。这意味着有三个输入种子映射到int.MaxValue
,只有一个映射到零,而每个正整数(除了int.MaxValue
)对应两个输入值。这意味着有一条序列的概率高50%被选择,而另一条序列的概率低50%。不幸的是,连接链接已经失效。 - phoog如果您正在寻找真正的随机数,那么您应该考虑使用利用自然现象的在线随机数生成器,例如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)。
使用.NET的Random应该可以胜任这个任务:
var random = new Random(System.DateTime.Now.Millisecond);
int randomNumber = random.Next(1, 5000000);