示例:已知f()函数为3-11等概率返回,求35-53等概率返回。
public class HelloWorld {
public static void main(String []args) {
// 已知f()函数为3-11等概率返回,求35-53等概率返回。
// check();// check(f)
// 利用已知f()函数,可以推理出0-1等概率发生器。
// 已知f() 为3-11等概率返回,那么,3-6出现时=0,8-11出现时=1,遇到7时重做
// 将7得概率等概率分给0、1,那么此时0-1就是等概率返回得。
// check();// check(f1)
// 那么要想求得35-53等概率发生,只需要求得0-18等概率返回再加上35即可。
// P(0-18)+35
// 重点:此时需要利用二进制位运算,18需要占用5个二进制位。
// 5个二进制位00000-11111代表0-31,通过0-1发生器可以求得0-31等概率发生。
// 只需要在大于18时重做,即可获得0-18等概率发生器。
// check();// check(f2)
check();// check(f3)
// 变形:通过0-1等概率发生器,得出000000-111111即0-63等概率发生器,当大于53或小于35时重做
// 此种方法时间复杂度超级不理想
}
// f() 3-11等概率返回
private static int f(){
return (int)(Math.random()*9) +3;
}
// f1() 0-1等概率返回
private static int f1(){
int ans =0;
do{
ans = f();
}while(ans == 7);
return ans <7 ? 0 : 1;
}
// f2() 00000-11111等概率返回 即 0-31等概率返回 大于18时重做 --> 0-18等概率
private static int f2(){
int ans = 0;
do{
ans = (f1()<<4) + (f1()<<3) + (f1()<<2) + (f1()<<1) + f1();
}while(ans > 18);
return ans;
}
// f3() P(0-18)+35
private static int f3(){
return f2() +35;
}
// f4() 000000-111111等概率返回 即 0-63等概率返回 大于53或小于35时重做 --> 35-53等概率
private static int f4(){
int ans = 0;
do{
ans = (f1()<<5)+(f1()<<4) + (f1()<<3) + (f1()<<2) + (f1()<<1) + f1();
}while(ans<35 || ans >53);
return ans;
}
// 验证等概率
private static void check(){
// 执行次数
int testTimes = 10000000;
// 定义验证数组
int[] che=new int[64];
for(int i=0;i<testTimes;i++){
// che[f()]++;
// che[f1()]++;
// che[f2()]++;
// che[f3()]++;
che[f4()]++;
}
// 打印随机结果
for(int j=0;j<che.length;j++){
System.out.println(j+" 这个数一共出现了"+ che[j] +" 次");
}
}
}