给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数
生活随笔
收集整理的這篇文章主要介紹了
给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
給你一個能生成1到5隨機數的函數,用它寫一個函數生成1到7的隨機數
文章目錄
- 給你一個能生成1到5隨機數的函數,用它寫一個函數生成1到7的隨機數
- 一、問題
- 二、分析
- 三、錯解
- 四、正解一
- 五、正解二
- 六、拓展
一、問題
已知rand5()產生1-5的隨機整數,利用該函數生成函數rand7()產生1-7的隨機整數。
二、分析
- rand5可以隨機生成1 ~ 5;目標生產rand7,使其可以隨機生成1 ~ 7。 rand5并不能直接產生6,7。我們可能想到 + 2,但是+ 2生產的是3 ~ 7,不滿足題意。
- 所以直接用rand5去實現函數rand7似乎不太好入手,那么我們反向思考一下,如果給你rand7,讓你實現rand5,這個好實現嗎?
- 其實反過來是可以的,因為rand7的生成隨機數范圍多了6和7,生成1 ~ 5的隨機數的概率仍然是隨機的,所以我們就需要對6和7下手。
- 怎樣操作6和7才可以使rand7生成隨機數的范圍為0 ~ 5并且忽略6和7呢?答案就是如果rand7生成的隨機數大于5,就繼續調用rand7,這樣rand7既滿足了生成隨機數的范圍為1 ~ 5并且保證了隨機
- 那么Rand5這個函數可以等概率地產生1到5的數嗎?
- 首先,它確確實實只會返回1到5這幾個數, 其次,對于這些數,都是由Rand7等概率產生的(1/7),沒有對任何一個數有偏袒(如果生成的隨機數大于5,就會繼續調用該函數), 直覺告訴我們,Rand5就是等概率地產生1到5的。
- 事實呢?讓我們來計算一下, 產生1到5中的數的概率是不是1/5就OK了。
- 比如說,讓我們來計算一下Rand5生成1 的概率是多少。上面的函數中有個while循環,只要沒生成1到5間的數就會一直執行下去。
- 因此,我們要的1可能是第一次調用Rand7時產生,也可能是第二次,第三次,…第n次。 第1次就生成1,概率是1/7;第2次生成1,說明第1次沒生成1到5間的數而生成了6,7, 所以概率是(2/7)*(1/7),依次類推。生成1的概率計算如下:
- 上述計算說明Rand5函數是等概率地生成1,2,3,4,5的(1/5的概率)。從上面的分析中, 我們可以得到一個一般的結論,如果a > b,那么一定可以用Randa去實現Randb。其中, Randa表示等概率生成1到a的函數,Randb表示等概率生成1到b的函數。代碼如下:
三、錯解
- 回到正題,現在題目要求我們要用Rand5來實現Rand7,只要我們將Rand5 映射到一個能產生更大隨機數的Randa,其中a > 7,就可以套用上面的模板了。 這里要注意一點的是,你映射后的Randa一定是要滿足等概率生成1到a的。比如,
- 上述代碼可以生成1到9的數,但它們是等概率生成的嗎?不是。生成1只有一種組合: 兩個Rand5()都生成1時:(1, 1);而生成2有兩種:(1, 2)和(2, 1);生成6更多。
- 它們的生成是不等概率的。那要怎樣找到一個等概率生成數的組合呢?
四、正解一
我們先給出一個組合,再來進行分析。組合如下:
5 * (Rand5() - 1) + Rand5();- 第一個Rand5產生1到5的隨機數,減1就產生0到4的隨機數,乘以5后可以產生的隨機數是:0,5,10,15,20。
- 第二個Rand5()產生的隨機數是1,2,3,4,5。那么我們可以得到1到25的隨機數, 而且每個數都只由一種組合得到,即上述代碼可以等概率地生成1到25。
- OK, 到這基本上也就解決了.
套用上面的模板,我們可以得到如下代碼:
int Rand5(){};int Rand7() {int num = INT_MAX;while(num > 7)num = 5 * (Rand5() - 1) + Rand5();return num; }五、正解二
- 上面的代碼有什么問題呢?可能while循環要進行很多次才能返回。
- 因為Rand25會產生1到25的數,而只有1到7時才跳出while循環, 生成大部分的數都舍棄掉了。這樣的實現明顯不好,我們應該讓舍棄的數盡量少。
- 于是我們可以修改while中的判斷條件,讓x與(最接近25)且(小于25)的(7的倍數)相比。
- 于是判斷條件可改為x > 21,于是x的取值就是1到21。 我們再通過取模運算把它映射到1-7即可。代碼如下:
- 這個實現就比上面的實現要好,并且可以保證等概率生成1到7的數。
六、拓展
- 讓我們把這個問題泛化一下,從特殊到一般。現在我給你兩個生成隨機數的函數Randa,Randb。Randa和Randb分別產生1到a的隨機數和1到b的隨機數,a,b不相等(相等就沒必要做轉換了)。現在讓你用Randa實現Randb。
- 通過上文分析,我們可以得到步驟如下:
- 步驟1:如果a > b,進入步驟2;
- 否則構造Randa2 = a * (Randa – 1) + Randa, 表示生成1到a2 隨機數的函數。如果a2 仍小于b,繼教構造 Randa3 = a * (Randa2 - 1) + Randa…直到ak > b,這時我們得到Randak , 我們記為RandA。
- 步驟2:步驟1中我們得到了RandA(可能是Randa或Randak ),其中A > b, 我們用下述代碼構造Randb:
- 從上面一系列的分析可以發現,如果給你兩個生成隨機數的函數Randa和Randb, 你可以通過以下方式輕松構造Randab,生成1到a*b的隨機數。
總結
以上是生活随笔為你收集整理的给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下使用C++操作redis数据
- 下一篇: TCP真的可靠吗