Random.Next()有多随机?

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;
    }
}

我不断改变随机数的最大限制(例如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
它之所以被称为伪随机,是有原因的。 - Brian Rasmussen
4
随机并不意味着“独特”。 - nos
22
恭喜你发现了生日悖论。 - kennytm
3
9、9、9、9 你确定这是随机的吗?这就是随机的问题,你永远无法确定。 <3 Dilbert - Pierre-Alain Vigeant
重复:https://dev59.com/J3I95IYBdhLWcg3wzRXv(只是语言不同,代码相同)。 - Dawid
3
根据您对随机的定义,考虑使用类似以下代码的“myRandom”类:class myRandom { int rnd; public int Next() { return rnd = ++rnd % int.MaxValue; } }可以保证不会出现重复,直到所有正整数都被使用过为止。 - Zano
5个回答

32
您没有在测试循环。您测试的是获得之前随机数所需时间,这是完全不同的概念。对于测试获得之前的随机数所需的时间,您的数据是准确的。请在维基百科中搜索“生日悖论”,以查看在若干次迭代后发生碰撞的概率图表。
巧合的是,上周我写了一篇关于这个主题的博客文章。它将于3月22日发布。有关详细信息,请点击我的博客
如果您想要测试伪随机数生成器的周期长度,那么您需要查找的不是之前获得过的数字,而是之前已经出现过的精确序列长度。有许多有趣的方法可以做到这一点,但最简单的方法可能是直接告诉您:Random的周期长度为几十亿,因此您不太可能编写一个能够发现这一事实的程序。您需要存储大量数字。
然而,周期长度并不是衡量伪随机数生成器质量的唯一标准。请记住,PRNG不是随机的,它们是可预测的,因此您必须非常仔细地考虑“随机性”的度量标准。
请给我们更多的细节:您为什么关心Random的“随机”程度?您使用它的应用程序是什么,您关心什么方面的随机性?

+1 @Eric:你在发布之前填充博客吗?这很有趣。 - Zano
7
@Zano: 是的,我一次写好一堆文章,然后设置它们每周发布两次。通常,我会提前两个月左右完成。而 Raymond Chen 每周会发表五到十篇文章,他的稿库有好几年的量;我不知道他是怎么做到的! - Eric Lippert
呵呵,这很有趣。但是,如果您提前几年完成,文章不会过时吗?例如,较新版本的.NET或C#会有不同的行为等。 - Joan Venge
1
@Joan:Raymond的大部分文章都涉及使用Windows API的C编程--这并不会很快改变,以至于许多文章过时。 - Ron Warholic
@EricLippert,你能告诉我吗?在这里:http://www.sanfoundry.com/csharp-program-generates-randam-numbers/,程序员生成随机数。但是它如何确定生成的限制呢?也就是说,在for循环中,他给出了最大值`i<10`,因此生成的数字最多有9位。那么它是如何直接取小于10的限制的呢? - Rahul Chaudhari

18

你认为如果数字不重复,随机性就会更好。这是错误的。

真正的随机性没有记忆性。当你选择下一个数字时,得到相同数字的几率与范围内的其他任何数字一样高。

如果你掷骰子得到了一个六,然后再次掷骰子,得到另一个六的概率并不会变小。如果你连续掷出两个六,这并不意味着骰子坏了。

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


它确实可能会。我的10面骰子中,数字8、9、0的出现频率比其他数字要高得多。它们非常适合漫威超级英雄游戏,但对于需要较低数字的其他游戏来说就不好用了。也就是说,骰子确实有可能坏掉。 - PRMan

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

2

2

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


1
我喜欢random.org如何使用大气干扰中的噪声。 - Pierre-Alain Vigeant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接