几道关于随机数的问题

1、给定一个等概率产生1-5的随机数rand1To5,要求不使用额外的随机函数实现等概率的产生1-7的随机函数rand1To7。

实现过程如下:

  1. rand1To5()等概率产生1,2,3,4,5
  2. rand1To5()-1 等概率产生 0,1,2,3,4
  3. (rand1To5()-1) * 5 等概率产生 0,5,10,15,20
  4. (rand1To5()-1) * 5  + rand1To5()-1 等概率产生 0,1,2,3,4,...,23,24 。这里是两次调用,不能化简。
  5. 如果步骤4产生的结果大于20,则重复步骤4,得到等概率的0,1,2...,20
  6. 对步骤5等概率的0,1,2...20 mod 7 得到等概率的 0,1,2,3,4,5,6
  7. 对步骤6得到的等概率 0,1,2,3,4,5,6 + 1 得到等概率的  1,2,3,4,5,6,7
public int rand1To7() {
    int num = 0;
    do {
        num = (rand1To5() - 1) * 5 + rand1To5() - 1;
    } while (num > 20);
    return num % 7 + 1;
}

总结:其实我们可以利用这种思路产生任意的等概率随机数。比如,我们需要构建 1-50的等概率随机数,在步骤4中我们得到了0-24的等概率随机数,接下来我们执行 ((rand1To5()-1) * 5  + rand1To5()-1) * 25 + (rand1To5()-1) * 5  + rand1To5()-1 可以得到 0-624的等概率随机数,然后大于599的都不要,在对结果 mod 50 然后在加1,就得到1-50的等概率随机数了。


给定一个以p概率产生0,1-p概率产生1的随机函数rand01p(),实现等概率的0/1随机数函数

显然rand01p()生成01和10的概率均为p(1-p)

利用这个特性就可以实现01等概率的随机数了:

public int rand01() {
    int num;
    do {
        num = rand01p();
    } while (num == rand01p());
    return num;
}

 

相关题目:

有两个随机数产生器,R1以0.7的概率产生1,以0.3的概率产生0,而R2以0.3的概率产生1,0.7的概率产生0.问如何组合这两种产生器,使新得到的随机数产生器以0.5的概率产生1,0.5的概率产生0。随机数产生器可复用。

R1 + R2     

x012
p0.210.580.21

   所以为0时输出0,为2时输出1,为1时继续迭代。



给定一个分类器p,它有0.5的概率输出1,0.5的概率输出0。Q1:如何生成一个分类器使该分类器输出1的概率为0.25,输出0的概率为0.75?Q2:如何生成一个分类器使该分类器输出1的概率为0.3,输出0的概率为0.7?

第一问,也即01概率之比为3:1,假设我们能生成一个0,1,2,3的等概率随机数,那么0,1,2时输出0;3时输出1。有01等概率生成0-3等概率可以参考前面的步骤实现,就是 rand01() * 2 + rand01()

第二问,01概率之比为7:3,同样我们生成一个0,1,2,3,4,5,6,7,8,9的等概率随机,然后0-6时输出0, 7-9时输出1。步骤和前面的一样,就不在赘述了。


现在有一个可以随机数1-9的均匀随机函数,要求推到出一个1-7的均匀随机函数。

分析:经历过上面的洗礼,我想这题应该很清晰了,就是丢掉8,9。

如果面试官接着问道,如果一直产生8,9怎么办?一直丢掉吗?

这里我给出一种我的想法,由1-9的等概率随机数,我们可以产生0-80的随机数,步骤和上面一样,那么我们 0-10输出1, 11-21生成2, ...,66-76输出7, 77-80丢弃,那么这样我们丢弃一个数的概率为 4/81比之前的2/9要小了。虽然这样丢弃一个数的概率变小了,但是每一个数至少要通过两次随机才可得到,不知是不是得不偿失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值