目錄
1、問題定義
已知有一個函數能夠產生1-N1之間的的隨機數(等概率),通過此函數將其改造成產生1-N2之間的隨機數(等概率)。設randN1()爲產生1-N1之間的隨機數的函數,需要將其改造成randN2()。
2、分下列兩種情況進行討論
情況一:若N1 >= N2時
我們可以用一個例子來討論這個問題,如給定的函數產生1-50之間的隨機數,要將其改成生成1-15之間的隨機數。則可以這樣考慮,若要將1-50之間的數變爲1-15之間的數只需要對15取餘運算即可,但是50並不是15的整數倍數,因此無法保證等概率。我想你已經想到了解決辦法,即取1-50之間15的最大整數倍數進行取餘運算(即45),而大於45的數則捨棄並重新運算。
randN2(){
if(randN1() > 45) return randN2();
else return randN1() % 15 + 1;
}
情況二:若N1 < N2時
此時產生的隨機數範圍比要改造生成的隨機數範圍小,那麼可以先對其進行範圍擴大改造,具體方法如下:
1)構造式子(randN1() - 1 ) * N1,那麼其變爲生成0,N1,2N1,......,(N1-1)N1之間的數
2)再通過第一步的式子構造(randN1() - 1) * N1 + randN1(),那麼會生成1 - N1^2之間的數
3)若N1^2 >= N2則可以參照情況一進行計算,否則返回步驟1)繼續擴大構造成1 - (N1^2)^2之間的數,直至滿足情況一
3、典型例題:給定產生1-5的隨機數,求1-7的隨機數函數
// 隨機生成等概率1-5的函數實現
int random5() {
int x = rand(); //調用隨機函數
if (x > 32000) return random5();
return x % 5 + 1; //1-5
}
// 由random5()構造 random7()
int random7() {
int x = 5 * (random5() - 1) + random5();
if (x > 21) return random7(); // 篩選的過程
return x % 7 + 1;
}