1.已知fOrinal()函数可以等概率返回1~5(整数类型),要求等概率返回 1~7
//模拟系统给的fOrinal()函数,等概率返回1~5
public static int fOrinal() {
return (int) (Math.random() * 5) + 1;
}
第一步:利用fOrinal()函数等概率返回0和1(注意不是范围0~1,是返回数字0和数字1)
思路:因为fOrinal()函数等概率返回1~5,即调用fOrinal()函数
得到1的概率是20%,
得到2的概率是20%,
得到3的概率是20%,
得到4的概率是20%,
得到5的概率是20%,
那么得到1和2的概率是40%,得到4和5的概率是40%,二者概率相同
如果判断fOrinal()函数得到1或2,就返回0,
如果判断fOrinal()函数得到4或5,就返回1,
就可以等概率得到 数字0和数字1
public static int f2() {
int v = 0;
do {
v = fOrinal();
} while (v == 3);
return v < 3 ? 0 : 1;
}
第二步:利用f2()函数等概率返回1~7
思路:利用位运算,由于f2等概率返回0和1,
那f2<<2得到 000或者100,
同理f2<<1得到 00或者10,
f2<<0得到 0或者1,
三者二进制相加为 000~111的范围
也就是等概率返回0~7
然后遇0重做,同第一步原理,
就可以等概率得到1~7了
public static int f3() {
//111 表示7
int i = 0;
do {
i = (f2() << 2) + (f2() << 1) + (f2() << 0);
} while (i == 0);
return i;
}
2.已知fOrinal2()函数可以以固定概率返回0和1但是二者概率不一样,要求等概率返回 0和1
//模拟系统给的fOrinal2()函数
public static int fOrinal2() {
return Math.random() < 0.7 ? 0 : 1;
}
思路:假设 0的概率是a ,1的概率是1-a
那么得到 0和0的概率是axa
得到 1和1的概率是(1-a)x(1-a)
得到 0和1的概率是ax(1-a)
得到 1和0的概率是ax(1-a)
可以看到如果调用两次fOrinal2,
得到0和1 与 1和0的概率是相同的,
就可以等概率得到0和1了
public static int f4() {
int i = 0;
do {
i = fOrinal2();
} while (i == fOrinal2());
return i;
}