2012-07-08 47 views
1

如果我想爲Int32可能包含的所有可能數字生成一個隨機數,下面的代碼是否是一種合理的方式?有什麼理由可能不是一個好主意嗎? (即均勻分佈至少Random.Next(好)本身反正)爲可能數字的全部範圍生成一個隨機Int32

public static int NextInt(Random Rnd) //-2,147,483,648 to 2,147,483,647 
    { 
     int AnInt; 
     AnInt = Rnd.Next(System.Int32.MinValue, System.Int32.MaxValue); 
     AnInt += Rnd.Next(2); 
     return AnInt; 
    } 
+0

不是'ANINT + = Rnd.Next(2);'的與'AnInt + = 1'相同? – Louis 2012-07-08 07:56:08

+0

你想讓一個範圍內的每個數字隨機輸出一次嗎? – Louis 2012-07-08 07:57:02

+0

它將添加0或1,以便我們達到Int32的最大可能值。 Random.Next()不會爲我們做不幸的事情。這可能是一個設計缺陷 – 2012-07-08 07:58:17

回答

2

您提出的解決方案會略微扭曲分佈。 minValue和maxValue的出現頻率將低於內部值。作爲一個例子,假設INT具有-2一個MINVALUE和爲1的MaxValue的下面是可能的初始值,與每個隨後將得到的值的隨機(2)之後:

-2: -2 -1 
-1: -1 0 
0: 0 1 

一半的負-2值將被修改爲-1,並且只有0的一半將被修改爲1。因此,值-2和1將發生比-1和0更低的頻率。

達米恩的解決方案很好。另一選擇將是:

if (Random(2) == 0) { 
    return Random(int.MinValue, 0); 
} else { 
    return 1 + Random(-1, int.MaxValue); 
} 

另一種解決方案,類似於達米安方法,並且比前一個更快的將是

int i = r.Next(ushort.MinValue, ushort.MaxValue + 1) << 16; 
i |= r.Next(ushort.MinValue, ushort.MaxValue + 1); 
+0

我喜歡你在那裏做的。我也在考慮你在代碼示例中所做的一些事情。你能解釋爲什麼這些值會被修改嗎?我不確定我跟着你 – 2012-07-08 08:49:31

+0

大概有一半的時間從整數範圍的下半部分(-2,147,483,648 ..- 1)中選取,另一半是從整數範圍的上半部分(0。 .2,147,483,647)。達米安的解決方案將比這個稍快。 – hatchet 2012-07-08 09:11:52

+0

是的,對我的系統進行的快速測試表明,達米安的解決方案確實是上述代碼的1.6倍。 – 2012-07-08 10:11:01

0

一個uniform distribution並不意味着你會得到每個數字只出現一次。爲此,你需要一個permutation

現在,如果你需要一個隨機排列所有你有點卡住了40億個數字。 .NET不允許對象大於2GB。你可以解決這個問題,但我認爲這不是你所需要的。

如果數量少(比如100或500萬,不到幾十億)不重複,你應該這樣做:

保持一個整數集,開始空。選擇一個隨機數字。如果它已經在集合中,請選擇另一個隨機數字。如果它不在集合中,請將其添加並返回。

這樣你保證每個號碼將只返回一次。

+1

您可以將所有40億個整數存儲在位數組中。每個位代表一個數字,如果該位爲0,那麼該數字還沒有被看到,並且如果它是1,則已經被看到。這將內存使用降至512MB。 – sean 2012-07-08 08:17:11

+0

是的,你可以。正如我所說的那樣,2GB的限制是有限的,這就是其中之一。但是,我不認爲OP想要對40億個數字進行排列,這是毫無意義的。 – zmbq 2012-07-08 08:26:17

3

您可以使用Random.NextBytes獲取4個字節,然後使用BitConverter.ToInt32將它們轉換爲int

喜歡的東西:

byte[] buf = new byte[4]; 
Rnd.NextBytes(buf); 
int i = BitConverter.ToInt32(buf,0); 
+0

這並不是專門回答我的問題,但我喜歡你的解決方案謝謝! – 2012-07-08 09:32:40

+0

@PaulMatthews - 我錯過了什麼方面的問題? – 2012-07-08 09:48:16

+0

我明確地問過我的代碼是否合理,如果不是的話。 – 2012-07-08 10:04:50

0

我有一個類從哪裏獲得隨機字節到8KB緩存,並通過從隨機字節轉換它們分發號碼。這給你完整的int分佈。 8KB緩衝區用於不需要爲每個新的隨機字節[]調用NextBytes。

// Get 4 bytes from the random buffer and cast to int (all numbers equally this way 
    public int GetRandomInt() 
    { 
     CheckBuf(sizeof(int)); 
     return BitConverter.ToInt32(_buf, _idx); 
    } 

    // Get bytes for your buffer. Both random class and cryptoAPI support this 
    protected override void GetNewBuf(byte[] buf) 
    { 
     _rnd.NextBytes(buf); 
    } 

    // cyrptoAPI does better random numbers but is slower 
    public StrongRandomNumberGenerator() 
    { 
     _rnd = new RNGCryptoServiceProvider(); 
    } 
相關問題