2011-01-27 108 views
7

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

回答

10

正如其他人所說,new Random()種子從當前系統時間的隨機數發生器。

我有an article更詳細地描述了這一點,包括對問題的解決方案,您可能會發現有用。基本上你想多次使用同一個Random的實例 - 但是觀察它是而不是線程安全。

+0

感謝您的答案和詳細的解釋。順便說一下,我正在閱讀你的C#深度2 :) – bla 2011-01-27 15:38:44

3

因爲它使用的時鐘作爲種子生成的數字,當你以這種方式產生的隨機數,你會得到

2

隨機數生成部分基於系統時鐘相同的數字,和C#太快速攪動它們...

11

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); 
    // ... 
1

如果不播種隨機的,你會得到相同數量的隨機是一個僞隨機發生器

使用的Thread.Sleep(1)您允許計時器提前併產生一個新的自動生成的種子。

「修復」的一種方法是創建1個隨機對象並重用它(就像其他一些人也回答的那樣),或者使用不同的隨機生成器。在http://msdn.microsoft.com/en-us/library/ctssatww.aspx

0

你使用任何隨機數發生器

更多信息是一個僞隨機數。這將始終具有預定義的種子值,適用於測試,但不適用於實現真隨機性的特徵。

您應該使用一個準隨機數字序列來生成隨機數字或更好,馬爾可夫鏈來生成最好的隨機數字。如果你打算使用這些隨機函數中的一個,你將不會有任何接近真正的隨機性的東西。