2012-03-24 66 views
4

我發佈了一堆開源隨機數生成器on my site,其中包括一個正態分佈的隨機數生成器。要生成一個範圍在10-20的隨機整數,我會寫一些像new NormalRandomGenerator(10, 20).Next()內部使用雙精度生成一個隨機數Integer

有人張貼此評論:

只是想知道是否有必要實施「INT下一步()」中的「雙NextDouble()」的 條款INT雙轉換(和 反之亦然)在某些硬件上可能非常慢,包括最近的PC 硬件,儘管目前我並不特別關注最新的CPU 。

我相信這個評論是指當有人呼籲我的一個類Next(20),在內部,該呼叫轉換爲類似(int)someMersenneTwister.NextDouble() * 20(我不記得,如果我用四捨五入)的事實。

我這樣實現它,因爲MT既快速又高效(雖然它有一個巨大的隨機週期)。據我所知,這是生成隨機數的標準方法 - 調用Next(),它返回範圍[0..1]中的雙精度值,然後將乘法和類型轉換爲int。

在我的設計方面,這裏有任何問題嗎?有沒有更好的方法(更高性能,更快)來生成不使用雙精度的整數隨機數?

對不起,如果這聽起來含糊不清。我不確定這裏是否有問題。

+2

我甚至不明白在有限的範圍內的整數怎麼能有一個正常/高斯分佈。該分佈在整個實軸上返回連續值。 – CodesInChaos 2012-03-24 17:32:29

+0

總是可以屏蔽掉較小數字的位數,我想這會更快。除此之外,我什麼也沒得到。 – SimpleVar 2012-03-24 17:35:53

+0

對於在給定的時間間隔檢查*均勻*整數[我的問題](http://stackoverflow.com/q/9499071/445517)和[我的隨機文庫(https://github.com/MerkatorProject/Merkator.Tools /tree/master/Merkator.Tools/Random) – CodesInChaos 2012-03-24 17:38:58

回答

3

不是你的問題的答案(因爲它在當前的形式IMO沒有意義)。但看看你的代碼,我看到了一些錯誤和其他問題:

  1. 播種。隨着時間的推移,種子會在幾毫秒內創建多個UniformRandomGenerator,從而導致種子碰撞。您從System.Random繼承該問題。
  2. MersenneTwister.NextDouble質量很差。 double大約有53位數字,你只填寫32.幾乎和System.Random一樣差,填充31。
  3. MersenneTwister.Next(int maxValue)現在在期望的時間間隔內延長了這個不好的雙倍。如果時間間隔長,這可能會導致強烈的偏見。 System.Random有一個非常類似的問題。
  4. Next(int minValue, int maxValue)計算maxValue-minValue
  5. 時的NormalRandomGenerator構造計算平均作爲this.Mean = ((max - min)/2) + min;包含一個int溢出。這是一個整數除法,因此如果max-min是奇數,則會導致偏差。奇怪的選擇,因爲this.Mean是一個雙。
  6. 計算正態分佈數的代碼看起來很奇怪,但我卻幫不了你那裏,因爲我不知道什麼是應該做的。

如果你想生成均勻隨機整數,這是我自己的問題的重複:Generating uniform random integers with a certain maximum,其重點是建立有效的整數,而不會引入偏差。我建議將我的答案與LukeH的答案結合起來。

+0

將所有問題放在一起的優秀答案! – 2012-03-24 20:21:05

+0

偉大的代碼審查,謝謝你。但就像你說的,不是我的問題的答案。 – ashes999 2012-03-24 21:00:57

+0

@ ashes999如果你指定了你真正想要的,我們可以回答這個問題。但是,現在你要求一些不可能/無意義的事情。 – CodesInChaos 2012-03-24 21:03:11

0

通過縮放在範圍內的雙[0..1)是細生成的隨機整數,其前提是所產生的雙被充分均勻地分佈。然而,包括Mersenne Twister在內的大多數僞隨機數生成器本地生成(32位無符號)整數,所以如果我們不需要使往返翻倍,那將會很好。

如果結合的N是2的冪,可以首先生成一個32位的隨機整數X和採取X模N.這是保證產生結果與均勻分佈。但是,如果N不是2的冪,以模造成在所得到的分佈的偏差(有更多的32位無符號整數爲其中X MOD 7是0大於6,例如)。如果N是小的,檢測這樣的偏見將需要大量的生成數字,但理論上,分佈將是不正確的。爲了生成真正均勻分佈在範圍[0..N]中的N不是2的冪的整數,我們可以求助於採樣算法:首先計算M,使得它是2的最小冪次大於比N(對於N = 13,M = 16等等)。然後生成一個32位整數X,計算Y = X mod M.現在,如果Y < N,我們完成了,Y是我們的數字。如果Y> = N,則丟棄它並生成另一個,直到出現Y < N.如果基礎prng是好的,生成的數字的期望數量永遠不會超過2(取決於N),並且當循環不保證終止時,它將以絕對的概率終止。在實際應用中,你想在循環中放置一個限制計數器,然後回退到另一個方法,以防止發生錯誤。

哪種方法最快?只有分析才能說明。這取決於硬件,語言和代碼質量。

更深入的討論可以在Knuth的TAOCP可以發現,第2部分