67. 總結篇:面試中隨機數"等概率"vs"不等概率"生成問題[random generator with equal or unequal probability]


【本文鏈接】

http://www.cnblogs.com/hellogiser/p/random-generator-with-equal-or-unequal-probability.html

1. 等概率生成

(1) rand5生成rand3

現在有一個Rand5函數,可以生成等概率的[0, 5)范圍內的隨機整數,要求利用此函數寫一個Rand3函數(除此之外,不能再使用任何能產生隨機數的函數或數據源),生成等概率的[0, 3)范圍內的隨機整數。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand5 to generate rand3
int  Rand3()
{
    
int  x;
    
do
    {
        x = Rand5();
    }
    
while  (x >=  3 );
    
return  x;
}

(2) rand3生成rand5

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand3 to generate rand5
int  Rand5()
{
    
int  x;
    
do
    {
        x = Rand3() * 
3  + Rand3();
    }
    
while  (x >=  5 );
    
return  x;
}

(3) rand5生成rand7

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand5 to generate rand7
int  Rand7()
{
    
int  x;
    
do
    {
        x = Rand5() * 
5  + Rand5();
    }
    
while  (x >=  21 );
    
return  x %  7 ;
}

(4) rand7生成rand10

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand7 to generate rand10
int  Rand10()
{
    
int  x;
    
do
    {
        x = Rand7() * 
7  + Rand7();
    }
    
while  (x >=  40 );
    
return  x %  10 ;
}

(5) rand_m生成rand_n

 歸納總結:將這個問題進一步抽象,已知random_m()隨機數生成器的范圍是[0, m) 求random_n()生成[0, n)范圍的函數,m < n && n <= m *m。

設t為n的最大倍數,且滿足t<m*m,即 t = ((m*m)/n)*n;

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand_m to generate rand_n
int  Rand_n()
{
    
int  x;
    
do
    {
        t = ((m * m) / n) * n;
        x = Rand_m() * m + Rand_m ();
    }
    
while  (x >= t);
    
return  x % n;
}

2. 不等概率生成

(1) 如何產生如下概率的隨機數?0出1次,1出現2次,2出現3次,n-1出現n次?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  random( int  size)
{
    
while ( 1 )
    {
        
int  m = rand(size);
        
int  n = rand(size);
        
if (m + n < size)
            
return  m + n;
    }
}

(2) rand以不等概率生成01, 如何以1/n的等概率產生1~n之間的任意一個數?

已知隨機函數rand(),以p的概率產生0,以1-p的概率產生1,現在要求設計一個新的隨機函數newRand(),使其以1/n的等概率產生1~n之間的任意一個數。

解決思路:

可以通過已知隨機函數rand()產生等概率產生0和1的新隨機函數Rand(),然后調用k(k為整數n的二進制表示的位數)次Rand()函數,得到一個長度為k的0和1序列,以此序列所形成的整數即為1--n之間的數字。

注意:從產生序列得到的整數有可能大於n,如果大於n的話,則重新產生直至得到的整數不大於n。

第一步:由rand()函數產生Rand()函數,Rand()函數等概率產生0和1。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  Rand()
{
    
while ( 1 )
    {
        
int  i1 = rand();
        
int  i2 = rand();
        
if (i1 ==  0  && i2 ==  1 )
            
return   1 ;
        
else   if (i1 ==  1  && i2 ==  0 )
            
return   0 ;
    }
}

第二步:計算整數n的二進制表示所擁有的位數k,k = 1 +log2n(log以2為底n)

第三步:調用k次Rand()產生隨機數,產生的k個01序列表示1-n之間的數。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  newRand()
{
    
while ( 1 )
    {
        
int  result =  0 ;
        
for ( int  i =  0  ; i < k ; ++i)
        {
            
if (Rand() ==  1 )
                result |= (
1  << i);
        }
        
if (result <= n)
            
return  result;
    }
}

【本文鏈接】

http://www.cnblogs.com/hellogiser/p/random-generator-with-equal-or-unequal-probability.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM