给定一个等概率随机产生1~M的随机函数rand1ToM如下:

public int rand1ToM(int m) {
return (int) (Math.random() * m) + 1;
}

除此之外不能使用任何额外的随机机制。有两个输入参数分别为m和n,请用rand1ToM(m)实现等概率随机产生1~n的随机函数rand1ToN。

Solution

在做这道题之前,我们先来看一个例子,由rand1to5如何产生rand1to7?稍加思考,不难发现可以有以下做法:

rand1to5(5) 等概率产生: 1 2 3 4 5

rand1to5(5) – 1 等概率产生: 0 1 2 3 4

(rand1to5(5) – 1) * 5 等概率产生: 0 5 10 15 20

(rand1to5(5) – 1) * 5 + (rand1to5(5) – 1) 等概论产生: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

现在 (rand1to5(5) – 1) * 5 + (rand1to5(5) – 1) 的范围已经超过1-7了,因此不用继续再扩大随机数函数可以生成的范围。

现在的问题是,已有的0-24这5个数中,0-20通过模7可以生成3套0-6,也就是说0-20可以等概率生成0-6,通过加1即可等概率生成1-7。但是,由于21-24的存在,0-24生成0-3的概率会大于4-6(加1后生成1-4的概率会大于5-7),如何解决?如果随机数生成函数生成21-24范围的数,那么直接忽略这次随机数的生成。代码如下:

public int rand1To5() {
return (int) (Math.random() * 5) + 1;
}
public int rand1To7() {
int num = 0;
do {
num = (rand1To5() - 1) * 5 + rand1To5() - 1;
} while (num > 20);
return num % 7 + 1;
}

现在来看,如何解决rand1tom生成rand1ton。其实一句话就可以总结,即以m倍的规模不断扩大随机数范围直到超过1ton的范围,之后使用do while循环筛选掉多余的使得概论不均等的数即可。

进阶

如果预先给定的随机数生成器以p的概论生成0,(1-p)的概率生成1,那么怎么通过该随机数生成器等概率生成的1-n?

无论概率p怎么变化,连续两次生成0 1或者1 0的概率都是p(1-p),因此我们只要排除掉0 0和1 1的情况就可以等概率生成0 1,如下:

public int rand01p() {
// you can change p as you like
double p = 0.83;
return Math.random() < p ? 0 : 1;
} public int rand01() {
int num;
do {
num = rand01p();
} while (num == rand01p());
return num == 1 ? 1 : 0;
}

而通过0 1 来生成 1-n的方法和之前的是一样的。

 

rand_1tom 产生 rand_1ton的更多相关文章

随机推荐

  1. leetcode461

    public class Solution { public int HammingDistance(int x, int y) { ]; ]; ; ; do { aryA[i] = x % ;//将 ...

  2. jquery 返回浏览器顶部

    经常在网页中看到有这样的现象,点击一个按钮,然后页面会跳到页面的中指定的位置,那这种效果是怎么实现的呢? 很多网页都有这种效果:返回顶部或者跳到不同的楼层(以下是天猫的效果) 实现原理: 1.我们来看 ...

  3. mysql连接测试java脚本

    JDBC.java import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.uti ...

  4. vue.js简单添加和删除

    这只是个简单的添加和删除,没有连接后台数据的 <%@ page language="java" contentType="text/html; charset=UT ...

  5. JDK中的注解简单了解

    0.注解(注解是给编译器看的东东) 注解的定义方式是@Interface,注解属性定义是类似于普通类的方法定义的,注解属性赋值是使用default关键字完成的,如下图所示 注解在定义时可以给默认值,也 ...

  6. hikari链接池

    # 链接池 hikari: # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒 connection-timeout: 60000 # ...

  7. poj3273(二分)

    题目链接:https://vjudge.net/problem/POJ-3273 题意:给定n个数,将这n个数划分成m块,问所有块最大值的最小是多少. 思路:注意到所求值最大为109,所以可以用二分来 ...

  8. CSS如何作小于1PX的边

    小于1PX的边能使页面变得更加精致,那么具体怎么做呢? 主要思路就是设置伪元素先放大再通过变换缩小. 代码如下 .border { position: relative;//如果有圆角 } .bord ...

  9. 优秀的 Spring Cloud 开源软件

    Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据监控等,都可以用 ...

  10. CentOS_mini下安装docker之 安装 golang

    取消挂载: 命令:umount /mnt/cdrom 下载 Go 语言文件 -bit Linux wget http://www.golangtc.com/static/go/go1.4.2.linu ...