这是我认为的真正原因,Math.random返回一个0(包括)到1(不包括)之间的浮点数,类似于0-0.9999999999999999(我猜测)。看到这个信息,我们可以很容易地想到,好的,这是一个百分比,所以我们只需要做一些像这样的事情:
let max = 10;
console.log(Math.round(Math.random() * max))
好的,让我们来看看我们的Math.random数字在我们的范围内应该代表什么。
假设我们的范围是min=1和max=5,这就创建了五种不同的可能性:1、2、3、4、5。如果0.9999999999999999,或者为了简单起见,取1作为从Math.random获取的最大数字,我们可以将它除以我们的范围所具有的可能性的数量,例如1/max,得到大约0.2作为结果,这意味着每个可能性至少将等于这个数乘以它的值,也就是说Math.random值在以下范围内将满足每个可能性:
现在让我们看一下Math.round的作用:
console.log(0.25 * 5, 'rounded to:', Math.round(0.25 * 5));
console.log(0.31 * 5, 'rounded to:', Math.round(0.31 * 5));
console.log(0.85 * 5, 'rounded to:', Math.round(0.85 * 5));
如您所见,在某些情况下(最小值的浮点数和最大值的浮点数),Math.round 将无法返回我们期望的结果,比如在第一个例子中,我们期望得到2,因为0.25大于0.2,在最后一个例子中,我们期望得到5,因为0.85大于0.8。这意味着从0.21到0.299999999999999以及从0.81到0.899999999999999的每个浮点数都会产生意外的结果,这就是为什么 Math.floor 解决方案更受欢迎的原因。
我们可以把随机生成的浮点数除以固定的可能性浮点数,这样怎么样?
console.log(0.25 / (1 / 5))
console.log(0.31 / (1 / 5))
console.log(0.85 / (1 / 5))
如果您查看这些结果,可以通过将它们舍入并确保我们至少获得最小值来修复它们:在末尾添加最小值。
let min = 1;
let max = 5;
let r = Math.random();
let f = 1 / max;
let x = Math.floor(r / f) + min;
console.log(r, x);
现在我们有另一个问题,如果我们将最小值更改为除1以外的任何数字,我们需要调整我们的公式以涵盖可能性数量中创建的偏移量。因此,如果我们的范围更改为
min=2和
max=5,我们现在有四种可能性:2、3、4、5,我们的公式现在包括(max-min+1)来计算可能性的数量;+1使范围包含创造四种可能性所需的插槽:
let min = 2;
let max = 5;
let r = Math.random();
let f = 1 / (max - min + 1);
let x = Math.floor(r / f) + min;
console.log(r, x);
我们最终的函数应该是这样的:
const randomNumber = (min, max) => {
return Math.floor(Math.random() / (1 / (max - min + 1))) + min;
}
console.log(randomNumber(2, 5));
//If Math.random ever returns 0.999999999999999
console.log(Math.floor(0.999999999999999 / (1 / (5 - 2 + 1))) + 2);//Prints 5
console.log(Math.floor(0.249999999999999 / (1 / (5 - 2 + 1))) + 2);//Print 2
//Hope this never happens
console.log(Math.floor(0.25 / (1 / (5 - 2 + 1))) + 2);//Print 3
这与以下代码相同:
const randomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(randomNumber(2, 5));
//If Math.random ever returns 0.999999999999999
console.log(Math.floor(0.999999999999999 * (5 - 2 + 1)) + 2);//Prints 5
console.log(Math.floor(0.249999999999999 * (5 - 2 + 1)) + 2);//Print 2
//Hope this never happens
console.log(Math.floor(0.25 * (5 - 2 + 1)) + 2);//Print 3
Math.floor()
)向下取整以保持在你的范围内。 - DaveStSomeWhere