給定了一個可以生成1~n的隨機函數,求一個生成1~m的隨機函數。爲了方便,假設n<m,m<n*n。函數
有一種比較通用,但不必定高效的方法是:方法
一、 z = n *( rand_n() - 1 )+rand_n();此時z的取值範值範圍是[1,n*n],並且是等機率的取值。while
二、 剩下的就是將[1,n*n]映射到[1,m]。由於m<n*n,因此只須要以m個數做爲一個取值區間,從小到大進行映射,到最後的幾個數不滿m個,就捨棄,從新取值。生成
因此,首先肯定最後捨棄的那幾個數的個數,re = n*n%m,return
三、最後,當z的值在(n*n - re, n*n]之間的時候,從新取值。在[1,n*n-re]時,對m取餘,加一便可。
int rand_m()
{
int z;
int re = n*n%m;
do
{
z = n * ( rand_n() - 1 ) + rand_n();
} while(z > n*n - re)
return z%m + 1;
}
這種方法,採用捨棄一部分不符合要求的數值的方式,原則上舍棄的數值的比例越少越好,最差的狀況是捨棄約50%的數值。好比z的範圍是[1,10],m是[1,6],那麼7,8,9,10都是要捨棄的。