Rand5ToRand7等相关随机器构造问题

问题描述:

  • 给你等概率返回1~5的随机函数, 这是唯一的随机源。 请做出等概率返回1~7的随机函数。
  • 给你以p概率返回0, 以1-p概率返回1的函数p, 这是唯一的随机源, 请做出等概率返回0和1的随机函数。
  • 给你等概率返回1~m的随机函数, 这是唯一的随机源。 请做出等概率返回1~n的随机函数。

思路分析:

  • 第一个问题和第三个问题类似,第一个问题是第三个 问题的具体情况。先分析第一个问题:
    • 先根据1~5随机器生成01等概随机器,具体方法为将1~5随机器可能产生的结果1~5映射为等概的0~1,1,2映射为0,4,5映射为1,当随机数为3时,重新运行该随机起,这样便保证了01的等概。然后根据01等概随机器构造0~6等概随机器。看6可由几位二进制构成,便运行几次01等概随机器,以此来作为二进制数字的每一位。但是可能最终产生的结果会超过6,如111的情况,如果发生这种情况,便再重新运行三次随机器,直至随机数不为111(7)的情况,便得到了0~6等概随机器。此时将该随机器结果加1,可得到1~7随机器
    • 对于问题3,类似问题1,先根据1~m随机器构造01等概随机器,具体需要判断m的奇偶。若为奇数(如12345),则得到中间那个数(3)时需要重新运行随机器。若为偶数(123456),则一半(123)映射为0,一半(456)映射为1。 然后根据n-1的二进制位数 bits,决定运行bits次01等概随机器,来组成二进制数,当生成的二进制数数值大于 n-1 时,需要重新运行bits次随机器,这便得到了 0~n-1随机器,进而加1,得到 1~n 随机器
  • 对于问题2,需要一点简单的概率知识。运行两次该随机器,则01与10两种结果等概,都为 p(1-p),将01映射为0,10映射为1;那么如果出现00或者11的情况,则重新运行两次该随机器,便可得 01等概随机器

经验教训

  • 若要求生成m~n等概随机器也一样,转换成 生成 0~ n-m随机器的问题

代码实现:

//原工具:生成1~5的随机器
    public static int rand1To5() {
        return (int) (Math.random() * 5) + 1;
    }

    //根据1~5的随机器构造0~1的随机器
    public static int rand0To1() {
        int res = 0;
        do {
            res = rand1To5();
        }while (res == 3);
        return (res == 1 || res == 2)? 0:1;
    }

    //根据 0~1 的随机器构造 0~6 的构造器
    public static int rand0To6() {
        int res = 0;
        do {
            res = rand0To1() == 0? 0:1;
            res += rand0To1() == 0? 0:2;
            res += rand0To1() == 0? 0:3;
        }while (res == 7);
        return res;
    }

    //根据0~6的随机器生成1~7的构造器
    public static int rand1To7() {
        return rand0To6()+1;
    }

    //原构造器,p概率生成0,1-p概率生成1
    public static int rand01p() {
        // you can change p to what you like, but it must be (0,1)
        double p = 0.83;
        return Math.random() < p ? 0 : 1;
    }

    //根据p概率01随机源构造 等概率 01随机源
    public static int rand01() {
        int res = 0;
        do {
            res = rand01p() == 0? 0: 1;
            res += rand01p() == 0? 0: 2;
        }while(res == 0 || res == 3);
        return res == 1 ? 0 : 1;
    }

    //原构造器,1~m 等概率随机器
    public static int rand1ToM(int m) {
        return (int) (Math.random() * m) + 1;
    }

    //根据1~m 等概率随机器,构造01等概率随机器
    public static int rand0To1(int m) {
        int res = 0;
        if ((m^1) == 0) {
            do {
                res = rand1ToM(m);
            }while (res == m/2 + 1);
            return (res < m/2 + 1 )? 0:1;
        }else {
            res = rand1ToM(m);
            return (res <= m/2)? 0:1;
        }
    }

    //根据1~m 等概率随机器,构造01等概率随机器
    //然后再根据01等概率器,先生成 0~n-1等概率随机器,再构造 1~n等概率器
    public static int rand1ToN(int m,int n) {
        int cur = 1;
        int bits = 1;
        while (cur < n-1) {
            bits++;
            cur = cur + cur*2;
        }
        int res = 0;
        do {
            res = 0;
            int base = 1;
            while (bits > 0) {
                res += rand0To1(m) == 0? 0 : base;
                base *= 2;
                bits--;
            }
        }while (res > n - 1);
        return res + 1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值