2015-06-08 58 views
8

我試圖用對數分佈生成隨機整數。我使用下面的公式:以對數分佈和自定義斜率生成隨機數

idx = Math.floor(Math.log((Math.random() * Math.pow(2.0, max)) + 1.0)/Math.log(2.0)); 

此運作良好,併爲1000次迭代產生這樣的序列(每個數字代表了多少次生成的索引):

[525, 261, 119, 45, 29, 13, 5, 1, 1, 1] 

Fiddle

我我現在試圖調整這種分佈的斜率,所以它不會像現在這樣迅速下降併產生類似的東西:

[150, 120, 100, 80, 60, ...] 

盲目地使用係數並沒有給我想要的東西。任何想法如何實現它?

+1

將每個'2.0'設置爲更接近於'1.0'的公式。例如, '1.3' – zmii

+0

@zmii如果'max = 10'運作良好,但是如果'max = 2',它會產生更加明顯的斜率:'[830,170]'vs'[744,256]'2.0' – serg

+0

I這樣做:[僞隨機數與預定義分佈](http://stackoverflow.com/a/22422035/2521214) – Spektre

回答

4

您提到了一個對數分佈,但它看起來像您的代碼旨在生成一個截斷的幾何分佈,而不是它的缺陷。有多於一種稱爲對數分佈的分佈,它們都不常見。請澄清你是否真的意味着其中之一。

您計算floor [log_2 U]其中U從1到(2^max)+1均勻分佈。這有一個1/2 ^最大的機會產生最大值,但你把它夾到最大-1。所以,你有1/2^max的機會產生0,2/2^max的機會產生1,4/2^max的機會產生2,...達到1/2 + 1/2^max產生最大-1的機會。

出現在你的代碼,而是從問題的說明失蹤,是你身邊翻轉計算的指數與

idx = (max-idx) - 1 

在此之後,您將有機會產生0 1/2 + 1/2^max,並且你產生k值的機會是1/2 ^(k + 1)。

我認爲讓U在[1,2^max + 1]上是均勻的是錯誤的。相反,我認爲你希望U在[1,2^max]上是統一的。那麼你產生idx = k的機會是2 ^(max-k-1)/((2^max)-1)。

idx = Math.floor(Math.log((Math.random()*(Math.pow(2.0, max)-1.0)) + 1.0)/Math.log(2.0)); 

zmii的評論,你可以用接近1.0的值更換兩個2.0S得到一個平坦的分佈是不錯的。對於最小值最大值產生的結果不令人滿意的原因是,您從[1,1.3^max + 1]而不是[1,1.3^max]中統一採樣。當最大值較小而基數較小時,額外的+1會產生更大的差異。請嘗試以下操作:

var zmii = 1.3; 
idx = Math.floor(Math.log((Math.random()*(Math.pow(zmii, max)-1.0))+1.0)/Math.log(zmii)); 
+0

謝謝,它現在工作很好。 – serg