为何不使用Math.round替代Math.floor生成指定范围随机数?
为什么用
Math.round生成指定范围随机数不被推荐? 核心问题出在概率分布不均上,咱们拿你要生成1-3随机数的例子拆解:
首先明确Math.random()返回的是[0, 1)区间的浮点数——大于等于0,小于1。
先看被推荐的Math.floor写法
代码是Math.floor(Math.random() * (max - min + 1) + min),代入min=1、max=3后:
Math.floor(Math.random() * 3 + 1)
Math.random() * 3的范围是[0, 3),加1后变成[1, 4)- 用
Math.floor取整后:- 1对应
[1, 2)区间,对应Math.random() * 3的[0, 1),概率是1/3 - 2对应
[2, 3)区间,对应Math.random() * 3的[1, 2),概率是1/3 - 3对应
[3, 4)区间,对应Math.random() * 3的[2, 3),概率是1/3
三个数的概率完全均等,这是随机数生成的理想情况。
- 1对应
再看Math.round的写法
代码是Math.round(Math.random() * (max - min) + min),代入min=1、max=3后:
Math.round(Math.random() * 2 + 1)
Math.random() * 2的范围是[0, 2),加1后变成[1, 3)- 用
Math.round取整后:- 1对应
[1, 1.5)区间,对应Math.random() * 2的[0, 0.5),概率是1/4(25%) - 2对应
[1.5, 2.5)区间,对应Math.random() * 2的[0.5, 1.5),概率是1/2(50%) - 3对应
[2.5, 3)区间,对应Math.random() * 2的[1.5, 2),概率是1/4(25%)
明显能看到,中间的2概率是边界值1、3的两倍,概率分布严重不均。
- 1对应
通用情况的问题
不管你要生成什么范围的随机整数,只要用Math.round,边界的两个数的概率都会只有中间数的一半——因为round会把区间两端的半段范围映射到边界值,中间的整段映射到中间值。而Math.floor的写法能把整个范围均匀分成max - min + 1等份,每个整数对应一份,概率完全相等。
这就是为什么网上普遍推荐Math.floor的写法,而很少提Math.round的原因。
内容的提问来源于stack exchange,提问作者That_Programming_Enthusiast
相关产品推荐
相关产品推荐

