给定一个等概率随机产生1~5的随机函数如下
public int rand1To5(){
return (int)(Math.random()*5) + 1;
}
除此之外不能使用任何的随机机制,请实现等概率的产生1~7的随机数rand1To7()
解: rand1To5() 等概率的随机产生1,2,3,4,5
rand1To5()-1 等概率的随机产生0,1,2,3,4
采用5进值
(rand1To5()-1)*5 + rand1To5()-1 等概率的随机生成0,1,2,3,4,...,24。 这里前后两个函数是独立调用的。
考察mod7的剩余类,20mod7 = 6, 所以20刚好是7的两个周期
如果在前面产生到大于20的数,就再产生,这样就可以均匀尝生0~20之间的随机数
再mod7+1 即可以产生0到7之间的随机数
public int rand1To7() {
int num = 0;
do{
num = (rand1To5() - 1) * 5 + rand1To5()-1;
}while(num>20)
return num%7+1;
}
给定一个以p的概率产生0,以1-p的概率产生1的随机函数rand01p
实现产生1~6的随机函数
虽然产生0和1的概率不相等,但是产生01和10的概率相等,均是p(1-p)。所以可写出产生等概率0,1的函数
public int rand01p()
{
double p = 0.83;
return Math.random() < p ? 0 : 1;
}
public int rand01(){
int num;
do{
num = rand01p();
} while(num == rand01p());
return num;
}
有了等概率产生0,1的函数,可以用rand01()*2+rand01()产生0~3的随机数
再利用4进制的特点,产生0~15之间的随机数
11 mod 6 = 5。所以再利用晒得办法等概率的产生0~11的整数
最后可以得到1~6的随机函数
进阶问题: 给定一个等概率随机产生1~m的随机数等概率的产生1~n的随机数
如果m>=n 直接先要找到最近的modn = n-1的数
对于n>m, 先用使用m进制插空法生成大于n的数,然后使用前面的过程