前言
Math.random
函数用于生成一个[0,1)
范围的随机数
但如需生成(0,5)
、(2,3]
之间的整数随机数,还需要与Math.floor
、Math.ceil
、Math.round
函数的配合,但是对于三种函数的选用,真是任意选其一都可以吗?
显然是不行的,毕竟三种函数的功能都不一致,怎么可能任意选其一都可以
测试
下面以生成[0,5]
之间的整数随机数为例,讲解三种函数不同的效果
Math.round生成随机数
Math.round
函数把一个数字四舍五入后最接近的整数
先使用运算表达式
Math.round(Math.random() * 5);
首先来看看生成100000次之后[0,5]
每个数字的概率吧
let countObj = {
0: 0,
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
};
const randomCount = 100000;
for (let index = 0; index < 100000; index++) {
let num = Math.round(Math.random() * 5);
countObj[num]++;
}
let proObj = {};
Object.entries(countObj).forEach(([key, value]) => {
proObj[key] = (value / randomCount) * 100 + "%";
});
明显0和5的生成概率只有其他数值的一半,用图分析一下
生成0的范围只有数值[0,5)
,生成5的范围也只有[4.5,5)
范围
这里可以改一下生成规则,Math.random() * 6 - 0.5
生成数值范围是[-0.5,5.499999)
,再执行Math.round
Math.round(Math.random() * 6 - 0.5)
这里不是万事大吉哦!!!
但是还是要你提醒你Math.random()
生成的数值范围是[0,1)
,当Math.random()
生成0时,Math.random() * 6 - 0.5
的值就是**-0.5**,再执行Math.round
之后值就是**-1了,但是-1**不在[0,5]
的范围哦,BUG不就出来了
Math.ceil
Math.ceil
总是向上舍入,并返回大于等于给定数字的最小整数
生成表达式
Math.ceil(Math.random() * 5);
看看100000次的生成效果吧
let countObj = {
0: 0,
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
};
const randomCount = 100000;
for (let index = 0; index < 100000; index++) {
let num = Math.ceil(Math.random() * 5);
countObj[num]++;
}
let proObj = {};
Object.entries(countObj).forEach(([key, value]) => {
proObj[key] = (value / randomCount) * 100 + "%";
});
0几乎永远取不到,你可能会疑惑,上面都是*0%*了,为什么还说是几乎喃?
不要忘了Math.random()
生成的数值范围是[0,1)
,0是有很小的概率取到的哦
这里可能你会发现除0以外的其他数字概率几乎都是相同的呀,我们能不能改一下表达式
Math.ceil(Math.random() * 6) - 1
Math.ceil(Math.random() * 5)
可以生成*[1,5]的数值,那么Math.ceil(Math.random() * 6)
就能生成[1,6]数值,这里只需要将结果-1*,不是*[1,5]*,属实是曲线救国了
但是还是要你提醒你Math.random()
生成的数值范围是[0,1)
,当Math.random()
生成0时,那么Math.ceil(Math.random() * 6)
的值就是**-1**,这不就是BUG嘛!!!
Math.floor
Math.floor()
返回小于等于一个给定数字的最大整数
生成随机数表达式
Math.floor(Math.random() * 5)
还是生成100000看看效果吧
let countObj = {
0: 0,
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
};
const randomCount = 100000;
for (let index = 0; index < 100000; index++) {
let num = Math.floor(Math.random() * 6);
countObj[num]++;
}
let proObj = {};
Object.entries(countObj).forEach(([key, value]) => {
proObj[key] = (value / randomCount) * 100 + "%";
});
这里需要注意Math.floor
向下取整,Math.random()
生成值的范围[0,1)
,*5的只能取到[0,4]
,那么可以**6*
Math.floor(Math.random() * 6)
Math.ceil
、Math.round
都会在Math.random()
生成0时卡壳,但是可以看出Math.floor
并不会
总结
生成随机数整数时一定要用Math.floor
,完整的表达式是
Math.floor(Math.random() * ((maxValue - minValue) + 1)) + minValue