基于java中random的简单算法题

一. 给定一个a~b区间随机数,更改为c~d区间随机数

思路是先将a~b区间的数 转变 为0/1等概率生成器,利用能够包含c~d得到最小二进制位 重新生成 0~e ( 0 < c < d < e)的区间随机数,进而完成从 a~b随机 到 c~d随机 的转变。

例如:将1~5随机 变为 1~7随机

  • 首先,调用random方法创建一个f1函数,用于生成区间1~5的随机整数。

public static int f1() {
        return (int)(Math.random()*5)+1;//随机生成区间1~5的整数
    }
  • 第二步,将f1转化为0/1等概率随机生成器(即把a~b等分位两部分),当调用f2函数时,随机生成0或1。

public static int f2() {
        int ans ;
        do {
            ans = f1();
        } while (ans == 3) ;//0~2对应0, 4~5对应1, ans==3 则再次调用f1
        return ans < 3 ? 0 : 1;
    }
  • 第三步,每一个f2所返回的值充当一个二进制位。(在这里,用3位二进制以表示生成0~7的等概率随机整数)

public static int f3() {
        return (f2()<<2) + (f2()<<1) + (f2()<<0);//生成0~7随机数
    }
  • 最后一步,循环调用f3直至返回一个位于区间1~7的整数

public static int f4() {
        int ans ;
        do {
            ans = f3();
        } while (ans == 0); //若ans==0,则再次调用f3直至ans不为0
        return ans;
    }
  • 简单的验证一下1000000次调用,1~7出现的概率分布。

public static void main(String[] args) throws IOException {
        //给定一个f(a,b)等概率随机数,映射返回一个g(c,d)等概率随机数
        int times = 1000000;
        int[] count = new int[8];
        for (int i = 0; i < times; i++) {
            int index = f4();
            count[index]++;
        }
        for (int i = 0; i < 8; i++) {
            System.out.println("随机数"+i+"生成了:"+count[i]+"次");
        }
​
    }
  • 输出结果:

随机数0生成了:0次
随机数1生成了:143132次
随机数2生成了:143031次
随机数3生成了:142630次
随机数4生成了:142429次
随机数5生成了:142740次
随机数6生成了:143160次
随机数7生成了:142878次

可以看出,1~7生成概率近乎相等。

二. 不等概率随机 到 0/1等概率随机

  • 假定现有一个x会以如下概率固定返回0/1,不关注x的内容。

01
P=0.831-P=0.19
public static int x() {
    return Math.random() < 0.84 ? 0 : 1;
}
  • 如何得到一个等概率返回0/1的y

01
P=0.51-P=0.5
  • 这里用到的依旧是二进制转换的思想:

11100100
(1-P)²P(1-P)P(1-P)
  • 不难看出,在这里只需要保留10和01(每当随机到11或00时,重新随机),即可得到两个等概率的数(10和01 其中 一个视做1 一个视做0)

public static int y() {
    int ans;
    do {
        ans = x();
    } while (ans == x()); //若两次x()相等,即出现00或11,重新随机
    //ans = 01 或 ans = 10
    return ans < 0.84 ? 0 : 1;
}
  • 由此即可将一个固定概率的0/1转变为等概率0/1。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superzheng__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值