如何利用一个小范围随机数,得到一个大范围等概率随机数

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/

posted @ 2022-01-22 21:44  7Aom1  阅读(313)  评论(0)    收藏  举报