正文
错误示范
我的错误写法:
Math.ceil(Math.random()*8+2)
解析:
产生该错误的原因是没有用区间思考时候没有考虑ceil函数的具体机制,直接使用函数造成的:
误认为以上代码等同于:
Math.ceil([0,1)*(n-m)+m)
//进一步对左开右闭区间处理如下:
Math.ceil([m,n))
// 于是取到m到n的任意整数,因为Math.ceil(0) == 0
实际上,Math.random() 能使Math.ceil取到0的是Math.random为0时,单点在区间中出现概率为0,因此测试结果表明无法取到左边界
网上错误方案
方案一
Math.round(Math.random()*8+2)
方案二
parseInt(Math.random()*8+2)
解析:
初看起来,似乎方案一完美实现了取到闭区间内所有整数,实际上:
[2,2.5) => 取2
[2.5,3.5) => 取3
...
[9.5,10) => 取10
注意看,取到2和10时的两个区间长度是取到其他数字区间长度的一半,意味着生成随机数的概率分布不均匀!
对于方案二,错误在于parseInt是用于解析字符串的函数:
parseInt(string, radix);
将其用于解析数字在规范中并未说明,但测试表明,当0.0000007类型的数字(超过6位的小数)会自动转换为7e-7的科学计数法,这样parseInt会解析为7,与我们本意解析为0不同,产生意外的结果
合理方案
Math.floor(Math.random()*9+2)
// 也就是区间长度加1与随机数相乘
Math.floor(Math.random()*(m-n+1)+n)
解析:
这样操作使得分布均匀且不产生以外数字:
[2,3) => 取2
[3,4) => 取3
...
[10,11) =>取10
总结
- 常用产生闭区间内整数的方法是Math.floor
- parseInt应该只用于处理字符串的数字解析
评论 0
还没有评论,来抢个沙发吧。