根据一个随机数构造另外的随机数的解法
给定一个函数rand5(),生成rand7()可以随机等概率的生成1-7的整数
题目:
给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一样。现要求使用该函数构造函数rand7(),使函数rand7()可以随机等概率的生成1-7的整数
思路:
rand5() 它能够等概率生成 1-5 之间的整数。所谓等概率就是1,2,3,4,5 生产的概率均为 0.2 。现在利用rand5(), 构造一个能够等概率生成 1- 7 的方法。这里有两个特别重要的点,一是 如果 rand5() + rand5(), 我们能够产生一个均匀分布的 1 - 10 吗? 答案是否定的。比如对于 6来讲(4+2, 2+4, 3+3),它被生成的概率比1 (1+0,0+1)要大。
第二个点就是我们不可能用rand5()直接产生 1- 7 的数,不管你用加减乘除都不行。所以,我们要构造一个更大的范围,使得范围里每一个值被生成的概率是一样的,而且这个范围是7的倍数。
先产生一个均匀分布的 0, 5, 10, 15, 20的数,再产生一个均匀分布的 0, 1, 2, 3,4 的数。相加以后,会产生一个 0到24的数,而且每个数(除0外)生成的概率是一样的。我们只取 1 - 21 这一段,和7 取余以后+1就能得到完全均匀分布的1-7的随机数了。
public static int rand5(){
int n=(int)(Math.random()*5+1);
return n;
}
public static int rand7(){
int n,temp1,temp2;
while(true){
temp1=rand5();
temp2=rand5();
//n是可以取1~25的随机的数。
n=(temp1-1)*5+temp2;
//当n>21重新生成,即扔掉n>21的数,这样n只能取1~21
if(n>21){
continue;
}else{
break;
}
}
//对7取模就能取1~7之间的随机数
return 1+n%7;
}
为什么要用(rand5() - 1) * 5 + rand5()这个式子来计算,以及用这个式子计算的结果能保证概率相等。 (rand5() - 1) * 5 + rand5(): 当第一个rand5() = 1时,可以产生1,2,3,4,5,每个数产生的概率相等。 当第一个rand5() = 2时,可以产生6,7,8,9,10 每个数产生的概率相等。 当第一个rand5() = 3时,可以产生11,12,13,14,15,每个数产生的概率相等。 当第一个rand5() = 4时,可以产生16,17,18,19,20,每个数产生的概率相等。 当第一个rand5() = 5时,可以产生21,22,23,24,25,每个数产生的概率相等。 第一个rand5()为1,2,3,4,5的概率相等,所以产生的1到25这25个数概率相等,去掉22,23,24,25,剩下的数产生的概率仍然相等。
若有rand3()如何求rand7()那?
同样的rand3()生成,1,2,3 按3倍数算生成,3,6,9,这时3倍的rand3()是能生成1…9的数字,即(rand3()-1)*3+rand3(),舍弃大于7的部分就能构造1-7的随机数
第一个rand3()=1时,可以产生1,2,3
第一个rand3()=2时,可以产生4,5,6
第一个rand3()=3时,可以产生7,8,9
如果以大的生成器生成更小的生成器那?
//rand8随机生成器制作一个1-7随机数生成器
public static int rand8(){
int n=(int)(Math.random()*8+1);
return n;
}
public static int rand7_1(){
int n;
do{
n=rand8();
}while(n>7);
return 1+n%7;
}
参考链接: