为什么不随机()随机?

时间:2011-01-27 15:05:49

标签: .net random

  

可能重复:
  Why does this Random Number Generator not random?

我有这个测试程序:

static void Main(string[] args)
{
    var randomNumbers = new Dictionary<int, int>();
    foreach (var s in Enumerable.Range(1, 500))
    {
        var rand = Rand5();
        if (!randomNumbers.ContainsKey(rand))
            randomNumbers.Add(rand, 1);
        else
            randomNumbers[rand] += 1;
    }

    randomNumbers
        .ToList()
        .ForEach(x => Console.WriteLine("{0}: {1}", x.Key, x.Value));
    Console.ReadLine();
}

static int Rand5()
{
    System.Threading.Thread.Sleep(1);
    return new Random().Next(1, 6);
}



如果我评论System.Threading.Thread.Sleep(1);,我会

5: 500

但如果我取消注释该行,我会得到随机数字。

2: 87
4: 94
1: 116
5: 108
3: 95

为什么代码行很重要?谢谢!

6 个答案:

答案 0 :(得分:11)

Random类型默认根据当前系统时间播种,该时间具有有限的粒度。

快速连续多次调用new Random().Next(1, 6)将构造许多具有相同种子值的Random个对象,从而产生相同的结果。 Thread.Sleep(1)调用“解决”了这个问题,只需将构造间隔时间间隔更远,增加了不同种子值的概率。

您需要在一次调用中保留一个特定的Random对象:

var randomNumbers = new Dictionary<int, int>();
var random = new Random(); // Re-use this, don't keep creating new ones.
foreach (var s in Enumerable.Range(1, 500))
{
    var rand = random.Next(1, 6);
    // ...

答案 1 :(得分:10)

正如其他人所说,new Random()从当前系统时间开始随机数生成器。

我有an article更详细地描述了这一点,包括问题的解决方案,您可能会发现它很有用。基本上你想多次使用Random的同一个实例 - 但是观察它不是线程安全的。

答案 2 :(得分:3)

因为它使用时钟作为生成数字的种子,当你以这种方式生成随机数时,你会得到相同的数字

答案 3 :(得分:2)

随机数生成器部分基于系统时钟,C#太快了,快速搅拌它们......

答案 4 :(得分:1)

如果你不对随机种子进行播种,则得到与Random是伪随机生成器相同的数字

通过使用Thread.Sleep(1),您可以使计时器前进并生成新的自动生成种子。

“修复”的方法是创建1个随机对象并重复使用它(就像其他人也回答一样),或者使用不同的随机生成器。

有关http://msdn.microsoft.com/en-us/library/ctssatww.aspx

的更多信息

答案 5 :(得分:0)

您使用的任何随机数生成器都是伪随机数。这将始终具有预定义的种子值,并且适用于测试,但不适用于实现真正随机性的功能。

您应该使用准随机数序列来生成随机数或更好的马尔可夫链以生成最佳随机数。如果您计划使用其中一个随机函数,则不会接近真正的随机性。