問題一:
已知一隨機發生器,產生0的概率是p,產生1的概率是1-p,現在要你構造一個發生器,使得它構造0和1的概率均為1/2;
構造一個發生器,使得它構造1、2、3的概率均為1/3;…,
構造一個發生器,使得它構造1、2、3、…n的概率均為1/n,要求復雜度最低。
解決方法:
原始的隨機數生成器,生成0 的概率為p,生成1的概率為1-p,那么怎么構造才能使得生成0和1的概率相等呢。或者說有兩個獨立的事件的概率是相等呢?
這樣來做一下,讓該隨機數生成器生成兩個數,那么序列是00,01,10,11概率分別為 p*p,p(1-p),(1-p)p,(1-p)*(1-p)
很明顯,這四種情況中存在兩個獨立的事件概率是相等。也就是01和10,那么我把01看成是0,10看成是1,那么他們輸出的概率均為p(1-p),其他的情況舍棄。這樣就得到了0和1均等生成的隨機器了。
這種解法可以推廣到n個數的情況,我們知道,取n個隨機數發生器,存在n個概率相同的獨立事件,我們只使用這n個事件就得到1/n的概率了。例如n=3,有8中情況000,001,010,011,100,101,110,111,其中001,010,100的概率都是p^2*(1-p)。
問題二:已知有個rand7()的函數,返回1到7隨機自然數,讓利用這個rand7()構造rand10() 隨機1~10。
解決方案:這個問題和上個問題不同的是,這里產生的序列,要變成和的形式或者其他的形式,那么概率就會發生變化了。
如果能夠得到一組等概率的數,不管是什么數,只要等概率而且個數大於10,那么問題就可以解決了。
發現(rand7()-1)*7+rand7(),可以等概率的生成1到49。
呵呵,這不就得了,只要把11-49砍掉就可以了。不過這樣的效率比較低。可以砍掉41-49,然后在把1-40映射到1-10(例如模10),那么問題也就解決了。
問題三:調用RANDOM(0, 1)實現RANDOM(a, b)
解決方案:這里的RANDOM(0, 1)是指等概率產生0或1,顯然,RANDOM(a, b) = a + RANDOM(0, b-a)
可以這樣做:
1,取 n=b-a+1,取最小的正整數m,使得 2^m >= n
2,調用RANDOM(0,1),輸出m-bit位整數N ( N >= 0 and N <= 2^m-1)
3, if N >=0 and N <= b-a
then return a+N
else 重新執行步驟 2
附:
// 問題一代碼實現
int MyRand() { int a = randP(), b = randP(); if(a != b) return a; return -1; }
//問題三的一種遞歸實現,n不是2的冪時有誤差
int random( a, b ) { if( a == b ) return a; if( random( 0, 1 ) ) return random( a, (a+b)/2 ); else return random( (a+b)/2 + 1, b ); }
參考鏈接:
1. CSDN_geekster-一些常見的概率生成器的題目
2. CSDN_chfe910-[面試題][數學與概率]設計隨機數生成器