已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。
//根据排列组合,连续算两次rand7出现的组合数是7*7=49,这49种组合每一种出现考虑是相同的。
//怎么从49平均概率的转换为1到10呢?
//方法是:
//1.rand7执行两次,出来的数为a1.a2.
//2.如果a1*7+a2<40,b=(a1*7+a2)>=40,重复第一步)
int rand10()
{
int a71, a72, a10;
do
{
a71 = rand7() - 1;
a72 = rand7() - 1;
a10 = a71 *7 + a72;
} while (a10 >= 40);
return (a10) % 10 + 1;
}
分析:
要保证rand10()在整数1-10的均匀分布,可以构造一个1-10*n的均匀分布的随机整数区间(n为任何正整数)。假设x是这个
1-10*n区间上的一个随机整数,那么x%10+1就是均匀分布在1-10区间上的整数。a10 = a71 *7 + a72; 会产生0~48共49个数,每个数
产生的概率都是1/49.生成的数只要<40,那么就跳出循环,那么共有40个数(0~39),每个数的概率相等,那么可以认为每个数的概率为1/40;
而且我们可以得到一般规律根据 RandM 得到 RandN
如果 M > N,那最简单,只要剔除 M > N 的数据,返回就可以了。
如果 M < N,首先用延展方法将 M 延展到 xM,xM > N然后再用上面的办法获取。
注:由朋友问为什么用while(x>40)而不用while(x>10)呢?原因是如果用while(x>10)则有40/49的概率需要循环while,很有可能死循环了。
转载自:http://blog.youkuaiyun.com/imcdragon/article/details/6838300
http://blog.youkuaiyun.com/furturerock/article/details/6850634