一、问题说明及示例:
通常java获取随机数,可以采用Math.random()方法,乘以一个数,然后取整
int random = (int) Math.round(Math.random() * size);
但是这个方法有一个问题,就是头和尾两个数,在四舍五入取整时,实际上会比中间的数字概率要低,比如0,有0.01~0.49四舍五入为0 ,而1的话,0.5~1.4之间的小数都可以四舍五入为1,也就是说通过上述方法,我们重复获取随机数,那么获取到0的概率会比获取到1的概率少一半
我们做个小实验,测试随机数统计,获取0-10共11个数字,获取1000次,新建一个map来保存统计数 key为数字,value为出现次数
public static void main(String[] args) {
//测试随机数统计,获取0-10共11个数字,获取1000次
int size = 10;
int countTotal = 1000;
//新建一个map来保存统计数 key为数字,value为出现次数
Map<Integer, Integer> countMap = new HashMap<>();
for (int i = 0; i < countTotal; i++) {
int random = (int) Math.round(Math.random() * size); // 采用自带的Math.random()获取随机数
int count;
if (countMap.containsKey(random)) {
//map里面有值,则获取次数并加1
count = countMap.get(random) + 1;
} else {
//map里面无值,首次出现
count = 1;
}
//保存随机数random数次count
countMap.put(random, count);
}
for (int random : countMap.keySet()) {
int count = countMap.get(random);
System.out.println("随机数 【 " + random + " 】 出现次数 -- " + count);
}
}
以上代码执行之后:
随机数 【 0 】 出现次数 -- 57 随机数 【 1 】 出现次数 -- 113 随机数 【 2 】 出现次数 -- 94 随机数 【 3 】 出现次数 -- 96 随机数 【 4 】 出现次数 -- 91 随机数 【 5 】 出现次数 -- 107 随机数 【 6 】 出现次数 -- 107 随机数 【 7 】 出现次数 -- 87 随机数 【 8 】 出现次数 -- 98 随机数 【 9 】 出现次数 -- 103 随机数 【 10 】 出现次数 -- 47
可以看出来随机数0和10的出现次数是1~9的一半左右
二、解决
在获取随机数时,去掉头尾两个数
public static int getRandom(int size) {
//获取0到size之间的一个随机数,包含0以及size
return getRandom(0, size);
}
public static int getRandom(int start, int end) {
BigDecimal max = BigDecimal.valueOf(end + 2);
BigDecimal min = BigDecimal.valueOf(start);
int random;
do {
//去掉头和尾两个数,因为头、尾数字在四舍五入之后得到的几率其实比中间的数少一半,并不能保证头尾的数字概率与其他数字相同
random = max.subtract(min).multiply(BigDecimal.valueOf(Math.random())).add(min).setScale(0, RoundingMode.HALF_UP).intValue();
} while (random == start || random == end + 2);
return random - 1;
}
测试:
public static void main(String[] args) {
//测试随机数统计,获取0-10共11个数字,获取1000次
int size = 10;
int countTotal = 1000;
//新建一个map来保存统计数 key为数字,value为出现次数
Map<Integer, Integer> countMap = new HashMap<>();
for (int i = 0; i < countTotal; i++) {
int random = getRandom(size); // 采用自带的getRandom(size)获取随机数
int count;
if (countMap.containsKey(random)) {
//map里面有值,则获取次数并加1
count = countMap.get(random) + 1;
} else {
//map里面无值,首次出现
count = 1;
}
//保存随机数random数次count
countMap.put(random, count);
}
for (int random : countMap.keySet()) {
int count = countMap.get(random);
System.out.println("随机数 【 " + random + " 】 出现次数 -- " + count);
}
}
结果:
随机数 【 0 】 出现次数 -- 83 随机数 【 1 】 出现次数 -- 86 随机数 【 2 】 出现次数 -- 98 随机数 【 3 】 出现次数 -- 90 随机数 【 4 】 出现次数 -- 95 随机数 【 5 】 出现次数 -- 104 随机数 【 6 】 出现次数 -- 89 随机数 【 7 】 出现次数 -- 83 随机数 【 8 】 出现次数 -- 100 随机数 【 9 】 出现次数 -- 85 随机数 【 10 】 出现次数 -- 87
java 随机数 源码https://download.csdn.net/download/weixin_47315082/88103385