如何利用一个小范围随机数,得到一个大范围等概率随机数
1、如何利用一个小范围随机数,得到一个大范围等概率随机数?
已知 rand_N() 可以等概率的生成[1, N]范围的随机数
那么:
(rand_X() - 1) × Y + rand_Y() ==> 可以等概率的生成[1, X * Y]范围的随机数
即实现了 rand_XY()
例如:(rand7()-1) × 7 + rand7()
这个例子可以等概率的生成[1,63]范围的随机数。
2、如何利用一个小范围随机数,得到一个确定的大范围等概率随机数?
这个确定的范围是指我们自己想要划分的范围。
拒绝策略:也就是某个采样结果不在要求的范围内,则丢弃它。
class Solution extends SolBase {
public int rand10() {
while(true) {
int num = (rand7() - 1) * 7 + rand7(); // 等概率生成[1,49]范围的随机数
if(num <= 40) return num % 10 + 1; // 拒绝采样,并返回[1,10]范围的随机数
}
}
}

3、由于拒绝策略效率极低,所以我们需要提高效率
如何提高?
利用这些范围外的数字,以减少丢弃的值,提高命中率总而提高随机数生成效率。
class Solution extends SolBase {
public int rand10() {
while(true) {
int a = rand7();
int b = rand7();
int num = (a-1)*7 + b; // rand 49
if(num <= 40) return num % 10 + 1; // 拒绝采样
a = num - 40; // rand 9
b = rand7();
num = (a-1)*7 + b; // rand 63
if(num <= 60) return num % 10 + 1;
a = num - 60; // rand 3
b = rand7();
num = (a-1)*7 + b; // rand 21
if(num <= 20) return num % 10 + 1;
}
}
}

引用来源:https://leetcode-cn.com/problems/implement-rand10-using-rand7/

浙公网安备 33010602011771号