從最基礎的講起如何做到均勻的生成隨機數

2021-10-11 02:31:32 字數 3067 閱讀 5721

題目描述:470. 用 rand7() 實現 rand10()

因為是第一次接觸到這樣的題目,毫無思緒,對官方題解也是「不知道為什麼要這麼做」。看過一些題解之後才逐漸明白,現在讓我自己來寫題解,我打算先從簡單的開始講起。

假設已知rand2()可以均勻的生成[1,2]的隨機數,現在想均勻的生成[1,4]的隨機數,該如何考慮?

我想如果你也像我一樣第一次接觸這個問題,那麼很可能會這麼考慮——令兩個rand2()相加,再做一些必要的邊角處理。如下:

rand2() + rand2() = ? ==> [2,4]

1    +   1     = 2

1    +   2     = 3

2    +   1     = 3

2    +   2     = 4

// 為了把生成隨機數的範圍規約成[1,n],於是在上一步的結果後減1

(rand2()-1) + rand2() = ? ==> [1,3]

0       +   1     = 1

0       +   2     = 2

1       +   1     = 2

1       +   2     = 3

可以看到,使用這種方法處理的結果,最致命的點在於——其生成的結果不是等概率的。在這個簡單的例子中,產生2的概率是50%,而產生1和3的概率則分別是25%。原因當然也很好理解,由於某些值會有多種組合,因此僅靠簡單的相加處理會導致結果不是等概率的。

因此,我們需要考慮其他的方法了。

仔細觀察上面的例子,我們嘗試對 (rand2()-1) 這部分乘以 2,改動後如下:

(rand2()-1) × 2 + rand2() = ? ==> [1,3]

0            +   1     = 1

0            +   2     = 2

2            +   1     = 3

2            +   2     = 4

神奇的事情發生了,奇怪的知識增加了。通過這樣的處理,得到的結果恰是[1,4]的範圍,並且每個數都是等概率取到的。因此,使用這種方法,可以通過rand2()實現rand4()。

也許這麼處理只是我運氣好,而不具有普適性?那就多來嘗試幾個例子。比如:

(rand9()-1) × 7 + rand7() = result

a               b

為了表示方便,現將rand9()-1表示為a,將rand7()表示為b。計算過程表示成二維矩陣,如下:

可以看到,這個例子可以等概率的生成[1,63]範圍的隨機數。再提煉一下,可以得到這樣乙個規律:

已知 rand_n() 可以等概率的生成[1, n]範圍的隨機數

那麼:(rand_x() - 1) × y + rand_y() ==> 可以等概率的生成[1, x * y]範圍的隨機數

即實現了 rand_xy()

那麼想到通過rand4()來實現rand2()呢?這個就很簡單了,已知rand4()會均勻產生[1,4]的隨機數,通過取餘,再加1就可以了。如下所示,結果也是等概率的。

rand4() % 2 + 1 = ?

1 % 2    + 1 = 2

2 % 2    + 1 = 1

3 % 2    + 1 = 2

4 % 2    + 1 = 1

事實上,只要rand_n()中n是2的倍數,就都可以用來實現rand2(),反之,若n不是2的倍數,則產生的結果不是等概率的。比如:

rand6() % 2 + 1 = ?

1 % 2    + 1 = 2

2 % 2    + 1 = 1

3 % 2    + 1 = 2

4 % 2    + 1 = 1

5 % 2    + 1 = 2

6 % 2    + 1 = 1

rand5() % 2 + 1 = ?

1 % 2    + 1 = 2

2 % 2    + 1 = 1

3 % 2    + 1 = 2

4 % 2    + 1 = 1

5 % 2    + 1 = 2

ok,現在回到本題中。已知rand7(),要求通過rand7()來實現rand10()。

有了前面的分析,要實現rand10(),就需要先實現rand_n(),並且保證n大於10且是10的倍數。這樣再通過rand_n() % 10 + 1 就可以得到[1,10]範圍的隨機數了。

而實現rand_n(),我們可以通過part 1中所講的方法對rand7()進行改造,如下:

(rand7()-1) × 7 + rand7()  ==> rand49()

但是這樣實現的n不是10的倍數啊!這該怎麼處理?這裡就涉及到了「拒絕取樣」的知識了,也就是說,如果某個取樣結果不在要求的範圍內,則丟棄它。基於上面的這些分析,再回頭看下面的**,想必是不難理解了。

class solution extends solbase }}

這部分具體的**是參考官方題解的,不過是我自己在理解了part 1和part 2之後才看懂的,一開始看真不知道為什麼(/(ㄒoㄒ)/~~...

根據part 1的分析,我們已經知道(rand7() - 1) * 7 + rand7() 等概率生成[1,49]範圍的隨機數。而由於我們需要的是10的倍數,因此,不得不捨棄掉[41, 49]這9個數。優化的點就始於——我們能否利用這些範圍外的數字,以減少丟棄的值,提高命中率總而提高隨機數生成效率。

class solution extends solbase }}

如何做到ERP基礎資料的整理?

參與過erp專案實施的人都應該知道,erp專案實施能夠成功,關鍵在於細節。有人這樣說,erp不難,只是很繁。這裡所說的繁,指的就是整理erp基礎資料的過程。整理erp基礎資料的確很繁瑣,這個過程並不比erp上線輕鬆,但它並不難,只要堅持,就一定能夠實現。erp專案實施成功靠的是三分技術,七分管理,十...

如何做到有效的溝通?

本文不敢談高效溝通,只根據作者感受談談如何做到有效溝通。生活和工作中溝通不可或缺,因為溝通不暢,溝通不到位造成的問題也是數不勝數,導致諸多無端的煩惱。那麼如何做到有效溝通呢?本人總結以下幾點,供參考 1,深入了解目的。做事要動腦筋,從別人的角度出發,了解做事背後要達成的真正的目的。本著有助於解決問題...

從pr的最簡工作流開始講起

1 pr的用途 2 專案視窗 3 序列視窗 按alt鍵並滾動滑輪可以縮放時間軸的顯示比例,在音訊軌按alt鍵並滾動滑輪可以放大音訊的波形 4 預覽視窗 用於實時預覽時間線上的素材效果 5 效果控制項視窗 可以對素材的基本屬性做出調整,也可以調整新增在素材上的效果引數 6 效果視窗 pr中需要用到的各...