为什么不随机()随机?

bla*_*bla 7 .net 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);
}
Run Code Online (Sandbox Code Playgroud)



如果我评论出来System.Threading.Thread.Sleep(1);,我明白了

5: 500
Run Code Online (Sandbox Code Playgroud)

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

2: 87
4: 94
1: 116
5: 108
3: 95
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*Tao 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);
    // ...
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 10

正如其他人所说,new Random()从当前系统时间播种随机数发生器.

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