【问题标题】:How random is Random.Next()?Random.Next() 有多随机?
【发布时间】:2010-02-25 14:47:07
【问题描述】:

我一直在对 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% 的时间都在这个平均值范围内。我不认为我们可以称它为随机。

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

【问题讨论】:

  • 它被称为伪随机是有原因的。
  • 随机并不意味着“独特”。
  • 恭喜你发现了生日悖论。 (en.wikipedia.org/wiki/Birthday_problem)
  • 9, 9, 9, 9 你确定这是随机的吗?这就是随机的问题,你永远无法确定。
  • 根据你对随机的定义,考虑使用类似class myRandom { int rnd; public int Next() { return rnd = ++rnd % int.MaxValue; } } Guaranteed noncyclic,直到所有正整数都用完为止。

标签: c# random birthday-paradox


【解决方案1】:

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

巧合的是,上周我写了一篇关于这个主题的博客文章。将于 3 月 22 日上线; see my blog然后了解详情。

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

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

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

【讨论】:

  • +1 @Er​​ic:你是否在发布前填满你的博客?这很有趣。
  • @Zano:是的,我一次写了一大堆文章,然后将它们设置为每周上线两次。在任何给定时间,我都提前了大约两个月。 Raymond Chen 每周发布五到十次,他的队列中有好几 ;我不知道他是怎么做到的!
  • 呵呵,真有趣。但是,如果您提前几年这样做,文章不会过时吗?例如,较新版本的 .NET 或 C# 的行为会有所不同,等等。
  • @Joan:Raymond 的大部分文章都是关于使用 Windows API 进行 C 编程的——它的变化速度还不够快,以至于很多文章都过时了。
  • 谢谢罗恩,这很有道理。
【解决方案2】:

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

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

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

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

【讨论】:

  • 实际上可能。我有 10 面骰子,比其他数字更频繁地出现 8,9,0。它们非常适合漫威超级英雄,但不适合其他需要较低数字的游戏。 IE。骰子可以被打破。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 我喜欢 random.org 如何使用大气干扰中的噪音。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多