为什么不随机()随机?

问题描述:

可能重复:
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 

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

+0

我认为将这些问题标记为愚蠢是徒劳无益的,因为大概三分之一*随机*标记的问题都是相同的问题。 – Joey 2011-01-27 16:49:40

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

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

+0

感谢您的答案和详细的解释。顺便说一下,我正在阅读你的C#深度2 :) – bla 2011-01-27 15:38:44

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

随机数生成部分基于系统时钟相同的数字,和C#太快速搅动它们...

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

快速连续多次调用new Random().Next(1, 6)将因此构造多个具有相同种子值的对象,产生相同的结果。 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); 
    // ... 

如果不播种随机的,你会得到相同数量的随机是一个伪随机发生器

使用的Thread.Sleep(1)您允许计时器提前并产生一个新的自动生成的种子。

“修复”的一种方法是创建1个随机对象并重用它(就像其他一些人也回答的那样),或者使用不同的随机生成器。在http://msdn.microsoft.com/en-us/library/ctssatww.aspx

你使用任何随机数发生器

更多信息是一个伪随机数。这将始终具有预定义的种子值,适用于测试,但不适用于实现真随机性的特征。

您应该使用一个准随机数字序列来生成随机数字或更好,马尔可夫链来生成最好的随机数字。如果你打算使用这些随机函数中的一个,你将不会有任何接近真正的随机性的东西。