用rand7()函数构造函数rand10()

题目要求:用一个已知均匀随机的rand7()(生成1~7等概率)来构造rand10()(生成1~10等概率)。

思路:题目要求用均匀分布生成另一个均匀分布。

1.前提:rand7()可以均匀生成1,2,3,4,5,6,7,目标是rand10()均匀生成1 ~ 10。

2.不能用简单的(rand7() * 10 / 7)之类的方法,因为它们不是均匀的(会偏向某些数)。

举例:

rand7()取值:1,2,3,4,5,6,7

乘以10:10,20,30,40,50,60,70

除以7:1,2,4,5,7,8,10

目标应该是1~10每个数的概率都为1/10,结果1,2,4,5,7,8,10的概率为1/7,3,6,9的概率为0,不合题意。

3.拒绝采样法:利用(rand7() - 1) * 7 + rand7()可以生成1 ~ 49之间的等概率随机数。

证明:

(1)令a = rand7() - 1,取值:0,1,2,3,4,5,6(均匀)。

(2)令b = rand7(),取值:1,2,3,4,5,6,7(均匀)。

(3)公式变成了a * 7 + b。这实际上是在构造一个两位的7进制数。

(4)a * 7只能取0,7,14,21,28,35,42。

(5)a * 7 +rand7(),其实就是0,7,14,21,28,35,42分别加上了1~7之间的数,正好组成了1~49的所有整数。

当a固定时:

a = 0:0 * 7 + b = 1 ~ 7。

a = 1:1 * 7 + b = 8 ~ 14。

a = 2: 2 * 7 + b = 15 ~ 21。

a = 3: 3 * 7 + b = 22 ~ 28。

a = 4: 4 * 7 + b = 29 ~ 35。

a = 5: 5 * 7 + b = 36 ~ 42。

a = 6: 6 * 7 + b = 43 ~ 49。

完美覆盖了1 ~ 49的所有整数。

之所以a * 7 + b这样构造是均匀的,是因为a和b是独立的随机变量,也就是两次独立的rand7()调用。概率计算:P(得到某个特定数 x) = P(a = 某值) × P(b = 某值)。实际上是在做笛卡尔积。通过 (a'-1)*7 + b 映射到 1~49,这是一个双射(一一对应),所以分布保持均匀。

举例:

复制代码
P(得到23) = P(a=3) × P(b=2) = (1/7) × (1/7) = 1/49

任何1 ~ 49的数都能唯一表示为a * 7 + b的形式,所以每个数的概率都是1/49。

4.(rand7() - 1) * 7 + rand7()生成等概率随机数的步骤:从1 ~ 49中只取1 ~ 40的数字映射到1 ~ 10,遇到41 ~ 49则重试。这是因为转换为rand10()的话,最大概率是将1 ~ 49分成10组,每组4个数(但49不是10的倍数),因此必须让num落在1 ~ 40范围内才有用,否则丢弃重新生成,保证1 ~ 10均匀。

附代码:

java 复制代码
class Solution {
    private Random random = new Random();

    // 假设提供的 rand7() 是均匀的
    private int rand7() {
        // random.nextInt(7)是生成一个0到6之间的随机整数(包含0,不包含7)
        //random.nextInt(7) + 1就是生成一个1到7之间的随机整数
        return random.nextInt(7) + 1;
    }

    public int rand10() {
        while (true) {
            int num = (rand7() - 1) * 7 + rand7(); // 1 ~ 49 均匀
            if (num <= 40) {
                // 将1 ~ 40的数映射到1 ~ 10
                // 如果是num % 10,那么1 % 10 + 1 = 2,映射错误,所以是(num - 1) % 10
                // 要求返回1 ~ 10,而不是0 ~ 9,所以应该 + 1,不加1的映射范围是0 ~ 9
                return (num - 1) % 10 + 1;
                // 如果 num = 41~49,则丢弃,重新生成
            }
        }
    }
}

ACM模式:

java 复制代码
import java.util.Random;
import java.util.Scanner;

class Solution {
    private Random random = new Random();

    // 假设提供的 rand7() 是均匀的
    private int rand7() {
        // random.nextInt(7)是生成一个0到6之间的随机整数(包含0,不包含7)
        //random.nextInt(7) + 1就是生成一个1到7之间的随机整数
        return random.nextInt(7) + 1;
    }

    public int rand10() {
        while (true) {
            int num = (rand7() - 1) * 7 + rand7(); // 1 ~ 49 均匀
            if (num <= 40) {
                // 将1 ~ 40的数映射到1 ~ 10
                // 如果是num % 10,那么1 % 10 + 1 = 2,映射错误,所以是(num - 1) % 10
                // 要求返回1 ~ 10,而不是0 ~ 9,所以应该 + 1,不加1的映射范围是0 ~ 9
                return (num - 1) % 10 + 1;
                // 如果 num = 41~49,则丢弃,重新生成
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt(); // 需要生成多少个随机数

        Solution solution = new Solution();
        for (int i = 0; i < n; i++) {
            System.out.print(solution.rand10());
            if(i < n - 1){
                System.out.print(" ");
            }
        }
        System.out.println();
        scanner.close();
    }
}
相关推荐
上课不要睡觉了1 天前
day13统计师考试(初级)统计量与抽样分布
统计·概率论·统计师考试
the sun342 天前
概率论:随机变量的定义、常见离散型、连续型随机变量
概率论
做cv的小昊3 天前
【TJU】应用统计学——第一周作业(1.1 数理统计的基本内容、1.2 数理统计的基本概念)
人工智能·笔记·考研·机器学习·数学建模·概率论
白云千载尽3 天前
深度思考——概率论与神经网络训练的关系
人工智能·神经网络·概率论
做cv的小昊4 天前
【TJU】研究生应用统计学课程笔记(5)——第二章 参数估计(2.3 C-R不等式)
c语言·笔记·线性代数·机器学习·数学建模·r语言·概率论
做cv的小昊4 天前
【TJU】应用统计学——第七周作业(4.2 多元线性回归分析、4.3 可化为线性回归的曲线回归、4.4 单因子方差分析)
线性代数·算法·数学建模·矩阵·回归·线性回归·概率论
点云侠6 天前
最小二乘拟合椭圆
线性代数·机器学习·概率论
the sun346 天前
概率论:条件概率与乘法公式深度剖析、常见概率类型
概率论
CM莫问7 天前
详解机器学习中的马尔可夫链
人工智能·算法·机器学习·概率论·马尔可夫·马尔科夫