Mozilla Developer Network 页面上有一些示例:
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
这是它背后的逻辑。这是一个简单的三法则:
Math.random() 返回介于 0(包括)和 1(不包括)之间的 Number。所以我们有一个这样的区间:
[0 .................................... 1)
现在,我们想要一个介于 min(含)和 max(不含)之间的数字:
[0 .................................... 1)
[min .................................. max)
我们可以使用Math.random 来获取[min, max) 区间内的通讯者。但是,首先我们应该通过从第二个区间中减去min 来考虑问题:
[0 .................................... 1)
[min - min ............................ max - min)
这给出了:
[0 .................................... 1)
[0 .................................... max - min)
我们现在可以申请Math.random,然后计算对应方。让我们选择一个随机数:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
所以,为了找到x,我们会这样做:
x = Math.random() * (max - min);
别忘了后面加min,这样我们就得到了[min,max)区间内的数字:
x = Math.random() * (max - min) + min;
这是 MDN 的第一个功能。第二个,返回一个介于min 和max 之间的整数。
现在要获取整数,您可以使用round、ceil 或floor。
您可以使用Math.round(Math.random() * (max - min)) + min,但这会导致分布不均匀。 min 和 max 两者都只有大约一半的滚动机会:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
将max排除在区间之外,它的滚动机会比min更小。
使用Math.floor(Math.random() * (max - min +1)) + min,您的分布非常均匀。
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
您不能在该等式中使用ceil() 和-1,因为max 现在滚动的机会略少,但您也可以滚动(不需要的)min-1 结果。