等概率随机函数的实现

【题目】:已知随机函数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);
	}
	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()的产生器。

 

【题目】:已知rand7() 可以产生 1~7 的7个数(概率),利用rand7()  产生rand10()   1~10(概率)

记住这道题重点是:概率

//rand7 产生的数概率是一样的,即1~7出现概率一样,由于我们对结果做了一定的筛选只能通过 1~5,而1~5出现的概率也是一样的,又由于范围为1~5 所以 temp1 出现 1~5的概率 为1/5 ,同理 后面的 出现 temp2 的概率为 1/2
//首先temp1出现在1~5的概率为1/5,而temp2出现 1~2 的概率为1/2,也就是说 5*(temp2-1) 出现5或0的概率为1/2,所以假如你要得到1~5的数的话 那么 5*(temp2-1) 必须0,所以因为你要保证 5*(temp2-1)=0,这个概率只有1/2,再加上 你前面指定1~5 的概率 为1/5 ,所以结果为 1/5*1/2=1/10
int rand10()
{
	int temp1;
	int temp2;
	do
	{
		temp1 = rand7();
	}while(temp1>5);
	do
	{
		temp2 = rand7();
	}while(temp2>2);
	return temp1+5*(temp2-1);
}


 

【题目】给定一个函数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.     }  

转自:http://blog.youkuaiyun.com/hackbuteer1/article/details/7486748

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值