美文网首页
02、介绍随机函数

02、介绍随机函数

作者: Albert_Yu | 来源:发表于2021-07-13 08:44 被阅读0次

    随机函数是平时刷题练习时验证正确性的比较灵魂的方法。
    java中提供了Math.random()函数:返回一个[0~1)等概率的一个double类型的值。

    1、验证代码

        package com.yubin.algorithms;
        
        /**
         * 介绍随机函数的使用
         * @author YUBIN
         * @create 2021-03-13
         */
        public class Code0007_RandToRand {
        
            public static void main(String[] args) {
                // 验证Math.random()函数[0,1)是等概率的
                int testTimes = 10000000;
                int count = 0;
        
                for (int i = 0; i < testTimes; i++) {
                    if (Math.random() < 0.75) { // 其概率应该约等于0.75
                        count++;
                    }
                }
                System.out.println((double)count / (double)testTimes);
        
                System.out.println("===========================");
        
                // [0,1)*8 => [0,8)
                count = 0;
                for (int i = 0; i < testTimes; i++) {
                    if (Math.random() * 8 < 5) { // 其概率应该约等于 5/8=0.625
                        count++;
                    }
                }
                System.out.println((double)count / (double)testTimes);
        
                System.out.println("===========================");
        
                int k = 9;
                // [0,k) 相当于 [0,l-1]
                int[] counts = new int[k];
                for (int i = 0; i < testTimes; i++) {
                    int ans = (int) (Math.random() * k);
                    counts[ans]++;
                }
                for (int i = 0; i < k; i++) {
                    System.out.println(i + "这个数,出现了" + counts[i] + "次");
                }
                System.out.println("===========================");
            }
        }
    

    2、题目一:如何利用Math.random()函数,把得到[0,x)范围上的数的概率从x调整成x2

    题目分析:经过上面的验证Math.random()随机函数[0,1)范围上概率是相等的,对应的0 ~ x范围的概率就是x,那么如何让0 ~ x的概率变成x2呢?
    利用Math.max(Math.random(), Math.random())
    Math.max(a1,a2); 只有当a1和a2两个值都在0 ~ x范围内的时候值才会在0 ~ x范围内,这样[0,x)的概率就变成x2了。

        private static double xToPower2() {
          return Math.max(Math.random(), Math.random());
        }
    

    注意:如果这里改成Math.min()函数的话,概率就变成 1-(1-x)2

    3、题目二:从1 ~ 5随机到1 ~ 7随机

    题目分析:程序中已提供一种1 ~ 5的随机是等概率的方法,如何利用该函数实现1 ~ 7的随机是等概率的。
    其实这个题目有一个限制就是1~7的等概率随机数不能使用 (int)(Math.random()*7)+1的方式,只能使用现成的方法。
    思路:
    已知函数是等概率返回[1,5]的整数
    那么1,2,3,4,5的概率分别是20%, 如果我使用1和2 表示0; 4和5表示1 当遇到3的时候再次随机即将得到3的概率分摊到其它4个数上面,此时得到1、2、4、5的概率都是25%,因此得到0的概率就是50%,得到1的概率也是50%。
    通过[1,5]等概率函数可以得到一个0,1等概率函数,然后再利用二进制的方式可以拿到一个0 ~ 7的等概率函数
    000,001,010,011,100,101,110,111。 因为7这个数至少需要3位来表示。
    代码实现:

        /**
         * 返回[1,5]的等概率随机数
         * 假设该方法是lib里面,不能修改
         * @return
         */
        private static int f1() {
            return (int) (Math.random() * 5) + 1;
        }
        
        /**
         * 随机机制,等概率返回0和1 只能使用f1函数
         * 分析 f1函数是等概率返回[1,5]的整数
         * 那么1,2,3,4,5的概率分别是20%, 如果我使用1和2 表示0; 4和5表示1 当遇到3的时候再次随机即将得到3的概率分摊到其它4个数上面,
         * 此时得到1、2、4、5的概率都是25%,因此得到0的概率就是50%,得到1的概率也是50%
         *
         * @return
         */
        private static int f2() {
            int ans = 0;
            do {
                ans = f1();
            } while (ans == 3);
        
            return ans < 3 ? 0 : 1;
        }
        
        // 得到000 ~ 111 做到等概率 0 ~ 7等概率返回一个 每一个数的概率是1/8
        private static int f3() {
            return (f2() << 2) + (f2() << 1) + (f2() << 0);
        }
        
        // 0 ~ 6等概率返回一个
        private static int f4() {
            int ans = 0;
            do {
                ans = f3();
            } while (ans == 7);
        
            return ans;
        }
        
        // 1 ~ 7等概率返回一个
        private static int g() {
            return f4() + 1;
        }
    

    同理:从a ~ b随机到c ~ d随机这个题目也可以使用上面这个方法来实现。
    将a ~ b变成01等概率发生器 ,将c ~ d变成0 ~ (d-c) 这时再看d-c需要几个二进制位, 同时如果超过d-c部分的重做即可

    4、题目三:01不等概率随机到01等概率随机

    分析:01不等概论,但是可以知道0和1是固定概率的,这样的话我们使用两位来表示
    00,01,10,11
    这每个数出现的概率都是第一位的概率 * 第二位的概率, 而已知的函数0和1虽然概率不一样但是0的概率*1的概率是一样的,这样01,10就是等概率的了, 使用01表示0,10表示1,其它情况重做即可,这样最后就能得到一个01的等概率随机。
    代码实现:

        // 已知的01不等概论函数,但是0和1的概率是固定的
        private static int x() {
            return Math.random() > 0.84 ? 0 : 1;
        }
        
        // 通过x函数得到01的等概率随机
        private static int y() {
            int ans = 0;
            do {
                // 第一次调用x函数
                ans = x();
            } while (ans == x()); // 第二次调用x函数 两次返回的结果不一样则说明要么是01 要么是10
        
            return ans;
        }
    

    相关文章

      网友评论

          本文标题:02、介绍随机函数

          本文链接:https://www.haomeiwen.com/subject/ptokpltx.html