2011-10-14 78 views
3

我發現一些有趣的東西(至少對我來說),而產生隨機整數,我無法解釋它自己,所以我想我會在這裏發佈。C#生成隨機INT - 神祕

我的需求很簡單:我是生成隨機積分(Int32)已ID和瞄準,以儘量減少衝突。發電時間不是問題。

我已經嘗試這些方法用於產生隨機整數:

1)

return rnd.Next(); 

其中RND是隨機型與從方法#3種子類字段。

2.)

return rnd.Next(Int32.MinValue, Int32.MaxValue); 

其中RND再次是隨機型與從方法#3種子類字段。

3)

var buffer = new byte[sizeof(int)]; 
    using (var rng = new RNGCryptoServiceProvider()) 
    { 
     rng.GetBytes(buffer); 
    }    
    return BitConverter.ToInt32(buffer, 0); 

注:我也試過有RNGCryptoServiceProvider作爲類字段的方含類緩解GC的工作初始化初始化一次,但我還是把同一時間產生,所以我想這將是「更隨機」。

4)

return new Random(Method3()).Next(); 

5)

return new Random(Method3()).Next(Int32.MinValue, Int32.MaxValue); 

我知道,在每次調用創建新的隨機(INT種子)是耗時的,但有少的碰撞,對不對?

好吧,現在是神祕的一部分。我認爲大多數碰撞會有方法#1和#2,其中#1會稍微快一些,更無碰撞,最少的碰撞會有方法#4和#5,其中#4會稍微快一些,碰撞更多,方法# 3會是某種妥協。

所以我做了一個測試來證明我的假設。我使用所提到的每種方法生成了10萬個隨機數(平均值),並將平均碰撞次數和平均時間用於生成一百萬個數字。結果(下面)對我來說有點令人驚訝。

結果:持續時間爲小時:分鐘:秒:毫秒格式

Method1: AvgCollisions: 235, AvgDuration: 00:00:00.3561967 
Method2: AvgCollisions: 116, AvgDuration: 00:00:00.4042033 
Method3: AvgCollisions: 115, AvgDuration: 00:00:04.6037259 
Method4: AvgCollisions: 234, AvgDuration: 00:00:09.2195856 
Method5: AvgCollisions: 233, AvgDuration: 00:00:09.1788223 

我再次運行測試幾次,它總是大約相同。

你也不奇怪嗎?對於我來說,時間並不令人意外,但結果對我而言意味着方法2最適合生成隨機數,因爲它是最隨機的,最快的,並且您可以設置最小和最大生成數。不知道Method2更可預測多少,因爲我不知道如何測試它。

有人可以解釋我什麼我doning錯了,或者爲什麼方法#4,#5不具有至少碰撞,爲什麼碰撞的百分比總是一樣的?它不應該是隨機的嗎?

編輯: 這裏是Visual Studio 2010的這個測試的解決方案我做:http://bit.ly/nxLODw

+1

您確定您在第一個結果中看到的碰撞次數嗎?其他一切都是有道理的,根據[this](http://stackoverflow.com/questions/1654887/random-next-returns-always-the-same-values)(還有數十億其他類似的討論 - 這是一個的五大編程誤區)。你可以發佈你的測試用例嗎? –

+4

你的#4 /#5假設是錯誤的。你不應該爲每一個隨機數字都調用'new Random()'。一次只做一次。 –

+0

Michael Petrotta的+1。 '和其他類似的討論在這裏' –

回答

6

唯一奇怪的行爲與方法5

的方法1,4,你生成數字範圍從0到int.MaxValue。

在方法2,3和5中,您生成的int.MinValue範圍內的數字爲int.MaxValue。

因此對於方法2和方法3,您的範圍大約是其兩倍,並且與方法1相比,它們有大約一半的碰撞。這對我來說似乎很正常。

那麼爲什麼方法5會產生與方法1和方法4一樣多的碰撞,儘管它會在更大範圍內產生數字?那麼,事實證明,System.Random構造函數獲取種子的絕對值。換句話說,它將隨機序列的數量減少到可能的一半。所以即使你從更大的範圍獲得數字,你也可以從更少的不同序列中產生它們。

+0

你明白了。不知道我怎麼會錯過1和4只能產生正數。現在對我來說,thx是有意義的。 – MSkuta

+0

現在提出一個新問題,爲什麼所有方法都有相同數量的碰撞?方法3不應該碰撞?因爲它是RNGCrypto ... – MSkuta

+0

不是。即使是「真正」的隨機序列,你也會碰撞。由於您只能生成大約1/2000或1/4000的可能數字,因此您的密碼太低而無法看到任何差異。 –

0

當你在那裏,你可能需要修改#3:

 var buffer = new byte[sizeof(int)]; 

     using (var rng = new RNGCryptoServiceProvider()) 
     { 
      rng.GetBytes(buffer); 
     } 

     return BitConverter.ToInt32(buffer, 0); 

這一個),確保您的數組是一個int(而不是幻數4的大小)和b)正確處置RNGCryptoServiceProvider是的IDisposable

+0

是的,這可能是個好主意,thx。 – MSkuta