2011-01-31 105 views
10

可能重複:
c# - getting the same random number repeatedly
Random number generator not working the way I had planned (C#)隨機數生成 - 數相同返回

我有一個建立INTS的隊列的方法:

public Queue<int> generateTrainingInts(int count = 60) 
    { 
     Queue<int> retval = new Queue<int>(); 

     for (int i = 0; i < count; i++) 
     { 
      retval.Enqueue(JE_Rand.rInt(2001, 100)); 
     } 

     return retval; 
    } 

JE_Rand .rInt()只是一個委託的功能ES的Random類的函數:

public static int rInt(int exclUB, int incLB = 0) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     int t = rand.Next(incLB, exclUB); 
     rand = null;    
     return t; 
    } 

但是當我打電話generateTrainingInts,相同數量的每次排隊。但是,如果我將rInt更改爲使用Random類的靜態實例,而不是本地實例(具有上面定義的函數範圍),那麼它似乎可以正常工作(排列隨機整數)。有人知道爲什麼會發生這種情況嗎?親愛的回答者,他們沒有透徹地閱讀我的問題, 就像你們中的一些人指出的那樣,我正在尋找一個很好的解釋爲什麼發生這種情況的原因。我不是在尋找解決同號碼問題的方法,因爲我已經解決了上述問題。感謝你的熱情,儘管:)我真的只是想了解這樣的事情,因爲我的第一個實現在概念上對我更有意義。

+0

似乎複製...看看像-http realted問題://stackoverflow.com/questions/1437825/random-number-generation-in-c – 2011-01-31 20:35:33

+0

它發生是因爲`Random`對象從初始化`環境。GetTickCount`,這是一個毫秒計時器。所以如果你在同一個毫秒內調用兩次`Random`構造函數,你將得到相同的初始值。 – 2011-01-31 20:36:23

+0

當rand與相同的種子(例如DateTime.Now.Millisecond)實例化時,它將返回相同的值序列。您應該實例化一次(並將其存儲在一個靜態變量中),或每次使用不同的種子。 – AFract 2011-01-31 20:41:31

回答

23

您需要保持相同的Random對象。把它放在你的靜態方法以外的靜態成員

private static Random rand = new Random(); 

public static int rInt(int exclUB, int incLB = 0) 
{ 
    int t = rand.Next(incLB, exclUB); 
    return t; 
} 

編輯
的原因是時鐘的有限分辨率用來初始化Random。 Random的後續初始化將在隨機序列中獲得相同的起始位置。當重複使用相同的隨機數時,隨機序列中的下一個值始終會生成。

5

嘗試一下下面的代碼,我想你會明白爲什麼:

void PrintNowAHundredTimes() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     Console.WriteLine(DateTime.Now); 
    } 
} 

Random對象被一遍又一遍地得到相同的種子。這是因爲由DateTime.Now返回的系統時間的粒度非常簡單,是有限的。例如,在我的機器上,數值每改變約15毫秒。所以在該時間段內連續的呼叫返回同一時間。

而且我懷疑你已經知道,使用相同種子值初始化的兩個對象Random將生成相同的隨機序列。 (這就是爲什麼它被稱爲,在技術上。)

你也應該知道,即使它是有道理的,你的方法內本地實例化一個新的Random對象,將其設置爲null仍然起不到任何作用(一次方法退出時將不再有對該對象的引用,因此無論如何它都將被垃圾回收)。

1
public class JE_Rand 
{ 
    private static Random rand= new Random(DateTime.Now.Millisecond); 

    public static int rInt(int exclUB, int incLB = 0) 
    { 
     int t = rand.Next(incLB, exclUB); 
     return t; 
    } 
}