1. 程式人生 > >隨機數產生轉換-根據(1,5)隨機數生成器,生成(1,7)之內的隨機數

隨機數產生轉換-根據(1,5)隨機數生成器,生成(1,7)之內的隨機數

1. 題目

    給定一個隨機數生成器,這個生成器能均勻生成1到5(1,5)的隨機數,如何使用這個生成器生成均勻分佈的1到7(1,7)的數?

2. 思路

   方法一:生成兩個(1,5)的隨機數,這樣一共是25種情況,注意這兩個數是有順序的,從這25種情況中,取前21種,每三種代表(1,7)中的一個數字,如果取到的是這21種以外的情況,丟掉重新取。

   方法二:生成三個(1,5)的隨機數,分別表示一個二進位制位,其中1和2對映為0,3跳過,4和5對映為1。這樣產生的三位二進位制數,即1-8這8個數字都是等概率的。如果產生的是8,那麼丟棄即可。

   方法三:生成兩個(1,5)的隨機數,產生一個兩位的五進位制數,5 * (random5() – 1) + random5()。這個公式能夠等概率產生1-25,即第一個隨機數代表:0,5,10,15,20,地位代表1,2,3,4,5。這樣對這個數字(1-25的數字),採用方法一的方法,只用1-21,分7分,代表1-7,22-25這4個數字扔掉。

3. 參考


問題描述

已知random3()這個隨機數產生器生成[1, 3]範圍的隨機數,請用random3()構造random5()函式,生成[1, 5]的隨機數?

問題分析

如何從[1-3]範圍的數構造更大範圍的數呢?同時滿足這個更大範圍的數出現概率是相同的,可以想到的運算包括兩種:加法和乘法

考慮下面的表示式:

3 * (random3() – 1) + random3();

可以計算得到上述表示式的範圍是[1, 9]  而且數的出現概率是相同的,即1/9

下面考慮如何從[1, 9]範圍的數生成[1, 5]的數呢?

可以想到的方法就是 rejection sampling 方法,即生成[1, 9]的隨機數,如果數的範圍不在[1, 5]內,則重新取樣

解決方法

int random5()
{
    int val = 0;
    do {
        val = 3 * (random3() - 1) + random3();
    } while (val > 5);
    return val;
}


歸納總結

將這個問題進一步抽象,已知random_m()隨機數生成器的範圍是[1, m] 求random_n()生成[1, n]範圍的函式,m < n && n <= m *m
一般解法:

int random_n()
{
    int val = 0 ;
    int t; // t為n最大倍數,且滿足 t <= m * m     
    do {         
        val = m * (random_m() - 1) + random_m();     
    } while (val > t);
    return val;
}


參考資料:

來自yaronspace.cn  本文連結:http://yaronspace.cn/blog/archives/1326