11

我一直在对 Random 类进行一些测试,并且使用了以下代码:

while (x++ <= 5000000)
{
    y = rnd.Next(1, 5000000);
    if (!data.Contains(y))
        data.Add(y);
    else
    {
        Console.WriteLine("Cycle {2}: Repetation found for number {0} after {1} iteration", y, x, i);
        break;
    }
}

我不断更改 rnd 最大限制(即 5000000)并更改了迭代次数,得到以下结果:

1) if y = rnd.Next(1, 5000) : The average is between 80 to 110 iterations
2) if y = rnd.Next(1, 5000000) : The average is between 2000 to 4000 iterations
3) if y = rnd.Next(1, int.MaxValue) : The average is between 40,000 to 80,000 iterations.

为什么我得到这些平均值,即在我检查每个值的 10 次中,80% 的时间我都在这个平均范围内。我不认为我们可以称它为随机。

我该怎么做才能得到一个相当随机的数字。

4

5 回答 5

31

您不是在测试周期。您正在测试获得以前拥有的随机数需要多长时间。那是完全不同的。你的数字可以用来测试你之前得到一个随机数需要多长时间。在“生日悖论”下的维基百科中查看经过一定次数的迭代后发生碰撞的概率图表。

巧合的是,上周我写了一篇关于这个确切主题的博客文章。将于 3 月 22 日上线;详情请看我的博客

如果您要测试的是伪随机数生成器的周期长度,那么您需要查找的不是您以前拥有的数字,而是您以前拥有的冗长精确的数字序列。有很多有趣的方法可以做到这一点,但我可能更容易告诉你:Random 的循环长度是几十亿,所以你不太可能编写一个发现这个事实的程序。你必须存储很多数字。

然而,周期长度并不是伪随机数发生器质量的唯一衡量标准。请记住,PRNG不是随机的,它们是可预测的,因此您必须非常仔细地考虑您的“随机性”指标是什么。

给我们更多细节:你为什么关心 Random 有多“随机”?您在使用什么应用程序?随机性的哪些方面对您很重要?

于 2010-02-25T14:51:36.703 回答
17

您假设如果数字不重复,随机性会更好。那不是真的。

真正的随机性没有记忆。当您选择下一个数字时,再次获得相同数字的机会与该范围内的任何其他数字一样高。

如果你掷骰子得到六,然后再掷骰子,再次得到六的机会不会少。如果你碰巧连续得到两个六,那并不意味着骰子坏了。

Random 类中的随机性当然不是完美的,但这不是您的测试所揭示的。它只是显示了每个随机数生成器都会出现的现象,即使实际上创建了真正的随机数而不仅仅是伪随机数。

于 2010-02-25T15:03:31.310 回答
3

您通过重复对来判断随机性,这不是随机性的最佳测试。您看到的重复类似于生日悖论:http ://en.wikipedia.org/wiki/Birthday_problem ,如果您不是在寻找特定事件,那么在小样本量下可能会发生重复事件。

于 2010-02-25T14:55:04.450 回答
2

根据http://msdn.microsoft.com/en-us/library/system.random.aspx上的文档

例如,要生成适合创建随机密码的加密安全随机数,请使用派生自 System.Security.Cryptography.. ::.RandomNumberGenerator 的类 ,例如 System.Security.Cryptography..::.RNGCryptoServiceProvider。

于 2010-02-25T14:49:13.320 回答
2

计算机无法生成真正的随机数。如果您需要一个真正的随机数(David 为您提供了 dot net 框架中的最佳选择),您需要一个外部随机源。

于 2010-02-25T14:52:02.940 回答