给定Math.random()
函数返回[0,1)和min
max
值之间的数字以指定范围,我们如何为以下情况生成数字:
我们想要整数:
A: (min,max) ?
B: [min,max) return Math.floor(Math.random() * (max - min)) + min;
C: (min,max] ?
D: [min,max] return Math.floor(Math.random() * (max - min + 1)) + min;
我们想要浮动:
A: (min,max) ?
B: [min,max) return Math.random() * (max - min) + min;
C: (min,max] ?
D: [min,max] ?
答案 0 :(得分:2)
<强>整数强>
你的B.公式是正确的,其他一切都是通过琐碎的+1
-1
更正获得的:
(min, max) = [min + 1, max)
,因此我们从B.获得
min + 1 + Math.floor(Math.random() * (max - min - 1))
min + Math.floor(Math.random() * (max - min))
(min, max] = max - [0, max - min)
中,也可以编写max - Math.floor(Math.random() * (max - min))
[min, max] = [min, max + 1)
:min + Math.floor(Math.random() * (max + 1 - min))
浮动。正如V13已经指出的那样,这个问题有点不合理:如果我们将单点视为测量零集,那么几乎(在测量 - 理论意义上)之间没有区别四组...但是,如果你想保证排除的区间边界永远不会(不仅仅是#34;几乎从不#34;)采样,如果你认为没有舍入错误,你可以做一些事情像这样:
答:var middle = (min + max) / 2; var sign = Math.random() > 0.5 ? 1 : -1; return middle + sign * (max - min) / 2 * Math.random();
这个解决方案在0
上放了一点点质量,但对于所有实际目的来说,这个数字应该可以忽略不计。
B:min + Math.random() * (max - min)
,是的。
max - Math.random() * (max - min)
,与上述对称。min + Math.random() * (max - min)
。 A和D之间的区别如下:如果我们尝试在A中使用公式min + Math.random() * (max - min)
,我们偶尔会得到0
(因为可能的数字范围实际上是有限的)。但是,没有合理的统计数据可能会抱怨D的上限没有被击中。
答案 1 :(得分:0)
整数:
return Math.floor(Math.random() * (max - min - 1)) + min + 1;
return Math.floor(Math.random() * (max - min)) + min + 1;
对于浮点数,您需要知道您拥有什么样的浮点运算。除非你使用特殊的库,否则float中的相等性通常不会发生,因此具有闭合范围没有任何意义。因此,四者之间应该没有区别,你可以选择:
return Math.random() * (max-min) + min;
对于有意义的问题,您需要定义最低可接受的平等范围(例如r=0.00000000000000001
)。之后,您可以将开放范围方程(即(min, max)
)转换为[min+r, max-r]
。
答案 2 :(得分:0)
我将首先定义接下来的两个辅助函数,然后使用它们来获取值。这些方法是您对B案例的定义。
int nextInt(int min, int max) {
return Math.floor(Math.random() * (max - min)) + min;
}
float nextFloat(float min, float max) {
return Math.random() * (max - min) + min;
}
然后是整数
花车是一个更复杂的案例。有些人可能会争辩说,是否包含终点并没有多大区别 - 特别是可以使用开放式解决方案而不是封闭 - 因为终点很少被选中。但由于完全有可能实现所有场景,我认为对如何实现它有数学兴趣。
答:在这种情况下,我们可以简单地确保再次滚动非法值:
float f;
do {
f = nextFloat(min, max);
} while (f == min);
return f;
<强> B:强>
return nextFloat(min, max);
C:这里我们只是切换端点
float f = nextFloat(min, max);
if (f == min) {
return max;
}
return f;
D:这是最复杂的情况,但可以通过以下方式实现:
float f = nextFloat(min, max);
if (f == min) {
return max;
}
return nextFloat(min, max);
案例A和D有点脏,因为它们可能需要生成多个随机数,这在某些特定情况下可能是一个问题。解决这个问题需要深入研究浮点的规范以找到替代实现。此外,应该注意的是,在情况D中,最大值的可适应性具有比任何其他数字更高的可用性,如果所引用的函数是完全均匀的(通常不是),但通常这只是理论上的问题。 (确切地说,如果在该范围内存在n个可能值,则最大值pmax = 1 /(n-1)的可适应性和任何其他值的可适应性是(1-pmax)/(n-1))。
应该注意在浮点情况A的精确实现中应该注意的一个小问题。函数的调用者可能会使用相邻的浮点调用它。通过对参数的任何虚拟检查都不容易看到,因此为了安全起见,应该限制循环执行的次数。