参加前端群答疑live时,有小伙伴提出了这样一个问题:
粗略一看,这个创造随机数的函数似乎没什么问题,Math.ceil(Math.random()*(max-min))
看上去是在获取[0,max-min]区间上随机的一个整数,再加上min的值,区间就刚好就变成了[min,max]。但是细细一想,很快就能发现问题的所在了--Math.ceil()
执行的是向上舍入,即它总是将数值向上舍入为最接近的整数。那么问题就产生了,只有Math.random()
值为0时,min + Math.ceil(Math.random()*(max-min))
才能取得最小值min,很显然这是不符合随机数要求的。
那该如何改进呢?JS内置的Math对象,舍入方法除了有向上舍入的ceil()
,还有向下舍入的floor()
以及标准舍入(即将数值四舍五入为最接近的整数)的round()
。而我们恰恰也可以利用floor()
来产成真正指定范围的随机整数数
function random(min,max) {
return min + Math.floor(Math.random()*(max - min + 1))
}
复制代码
因为Math.random()**(max - min + 1)
介于[0,max-min+1)之间,而floor()
由于向下取整特性,所以Math.floor(Math.random()*(max - min + 1))
落到了[0,max-min],而且不存在必须满足某种特殊条件才能取到某某特殊值的情况,所以用floor()
改写过的random()
是能满足面试题要求的。
既然用到了floor()
,可能有人就会好奇了,先前提到的第三种舍入方法round()
是不是同样也可以产生随机数呢。根据题设要求,我们很快能写出以下代码:
function random(min,max) {
return min + Math.round(Math.random()*(max-min))
}
复制代码
同样的,我们很快也能发现问题,那就是取值区间的边界值,也就是min和max,相对于取值区间内其他整数,能取到的概率大大变小。我们以min=0、max=2为例,根据使用round()
编写的随机数函数,产生随机数0的区间为[0,0.5),产生随机数1的区间为[0.5,1.5),产生随机数2的区间为[1.5,2)。很明显,边界值概率只有取值区间内其他整数值的1/2,所以用round()
也是无法生成真正的随机数的。
如何这篇文章对你有帮助,可以的话,点个喜欢呢