等概率隨機函數的實現 .

題目:已知隨機函數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。

  1. int Rand()  
  2. {  
  3.     int i1 = rand();  
  4.     int i2 = rand();  
  5.     if(i1==0 && i2==1)  
  6.         return 1;  
  7.     else if(i1==1 && i2==0)  
  8.         return 0;  
  9.     else  
  10.         return Rand();  
  11.     return -1;  
  12. }  
int Rand()
{
	int i1 = rand();
	int i2 = rand();
	if(i1==0 && i2==1)
		return 1;
	else if(i1==1 && i2==0)
		return 0;
	else
		return Rand();
	return -1;
}
第二步:計算整數n的二進制表示所擁有的位數k,k = 1 +log2n(log以2爲底n)
第三步:調用k次Rand()產生隨機數。

  1. int newRand()  
  2. {  
  3.     int result = 0;  
  4.     for(int i = 0 ; i < k ; ++i)  
  5.     {  
  6.         if(Rand() == 1)  
  7.             result |= (1<<i);  
  8.     }  
  9.     if(result > n)  
  10.         return newRand();  
  11.     return result;  
  12. }  
int newRand()
{
	int result = 0;
	for(int i = 0 ; i < k ; ++i)
	{
		if(Rand() == 1)
			result |= (1<<i);   //每次出現0,1的概率是相等的,那麼通過該表達式讓前k位中每位出現0或者1的概率一樣
	}
	if(result > n)
		return newRand();
	return result;
}


題目:
給定一個函數rand5(),該函數可以隨機生成1-5的整數,且生成概率一樣。現要求使用該函數構造函數rand7(),使函數rand7()可以隨機等概率的生成1-7的整數。
思路:
很多人的第一反應是利用rand5() + rand()%3來實現rand7()函數,這個方法確實可以產生1-7之間的隨機數,但是仔細想想可以發現數字生成的概率是不相等的。rand()%3 產生0的概率是1/5,而產生1和2的概率都是2/5,所以這個方法產生6和7的概率大於產生5的概率。
正確的方法是利用rand5()函數生成1-25之間的數字,然後將其中的1-21映射成1-7,丟棄22-25。例如生成(1,1),(1,2),(1,3),則看成rand7()中的1,如果出現剩下的4種,則丟棄重新生成。
簡單實現:

  1. int rand7()  
  2. {  
  3.     int x = 0;  
  4.     do  
  5.     {  
  6.         x = 5 * (rand5() - 1) + rand5();  
  7.     }while(x > 21);  
  8.     return 1 + x%7;  
  9. }  
int rand7()
{
	int x = 0;
	do
	{
		x = 5 * (rand5() - 1) + rand5();
	}while(x > 21);
	return 1 + x%7;
}
我的備註:
    這種思想是基於,rand()產生[0,N-1],把rand()視爲N進制的一位數產生器,那麼可以使用rand()*N+rand()來產生2位的N進制數,以此類推,可以產生3位,4位,5位...的N進制數。這種按構造N進制數的方式生成的隨機數,必定能保證隨機,而相反,藉助其他方式來使用rand()產生隨機數(如 rand5() + rand()%3 )都是不能保證概率平均的。
    此題中N爲5,因此可以使用rand5()*5+rand5()來產生2位的5進制數,範圍就是1到25。再去掉22-25,剩餘的除3,以此作爲rand7()的產生器。

給定一個函數rand()能產生0到n-1之間的等概率隨機數,問如何產生0到m-1之間等概率的隨機數?

  1. int random(int m , int n)  
  2. {  
  3.     int k = rand();  
  4.     int max = n-1;  
  5.     while(k < m)  
  6.     {  
  7.         k = k*n + rand();  
  8.         max = max*n + n-1;  
  9.     }  
  10.     return k/(max/n);  
  11. }  
int random(int m , int n)
{
	int k = rand();
	int max = n-1;
	while(k < m)
	{
		k = k*n + rand();
		max = max*n + n-1;
	}
	return k/(max/n);
}
如何產生如下概率的隨機數?0出1次,1出現2次,2出現3次,n-1出現n次?

  1. int random(int size)  
  2. {  
  3.     while(true)  
  4.     {  
  5.         int m = rand(size);  
  6.         int n = rand(size);  
  7.         if(m + n < size)  
  8.             return m+n;  
  9.     }  
  10. }  

轉自:http://blog.csdn.net/hackbuteer1/article/details/7486748

發佈了32 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章