问题

从1~5随机到1~7随机:即给定一个方法f,该方法能够等概率的返回1~5之间的整数(包括a和b),要求不用其他随机方法只能用f方法,使得等概率返回1~7之间的整数(包括c和d)。

解答

基本思路

第一步:利用f方法实现等概率返回0和1。由于f方法能够等概率返回1~5之间的整数,这个时候我们可以写一个新的方法f2,内部去调用f方法,拿到f方法的返回结果x,由于1~5之间有5个数,所以我们可以这样处理:如果x的值是1或者2,则f2方法返回0;如果x的值是4或者5,则f2方法返回1;如果x的值是3,则重新调用f方法并将返回值重新赋值给x,直到x的值不为3。这样经过改造后,相当于f方法返回的1、2、4、5是等概率的,也就做到了0和1等概率。

第二步:由于7用二进制表示为111,有三位,所以这个时候可以写一个新的方法f3,内部我们只需要调用三次f2方法,然后再利用二进制位运算中左移的方式将这三次调用的结果加起来,就得到了0~7的值。

第三步:由于题干要求1~7随机,所以这个时候我们可以再写一个新的方法f4,内部去调用f3方法,拿到返回结果后进行判断,如果返回值是0,则重新调用f3,直到返回结果不为0为止,这样就做到了1~7随机。

代码示例

public class RandomFromAbToCd {

    public static int f() {
        return (int) (Math.random() * 5) + 1;
    }

    public static int f2() {
        int num = f();
        while (num == 3) {
            num = f();
        }
        return num <= 2 ? 0 : 1;
    }

    public static int f3() {
        // 利用位运算中的左移将三次结果加起来,其中f2() << 0可以简写为f2(),这里只是为了格式对称
        return (f2() << 2) + (f2() << 1) + (f2() << 0);
    }

    public static int f4() {
        int num = f3();
        while (num == 0) {
            num = f3();
        }
        return num;
    }

    public static void main(String[] args) {
        int maxTimes = 10000000;
        int[] arr = new int[8];
        for (int i = 0; i < maxTimes; i++) {
            int num = f4();
            arr[num]++;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(i + "出现了" + arr[i] + "次");
        }
    }

}

运行结果为:

0出现了0次
1出现了1428801次
2出现了1427610次
3出现了1428738次
4出现了1429379次
5出现了1429315次
6出现了1428680次
7出现了1427477次

思考

从1~5随机到1~7随机只是这一类题型的具体代表,可以概括为从a~b随机到c~d随机,其中a、b、c、d都是整数,这种题型都可以用上面的算法去解决。

最后修改:2024 年 01 月 25 日
如果觉得我的文章对你有用,请随意赞赏