生成指定范围内的随机数 - 各种情况(int,float,inclusive,exclusive)

时间:2015-10-16 09:47:21

标签: javascript random floating-point integer range

给定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] ?

3 个答案:

答案 0 :(得分:2)

<强>整数 你的B.公式是正确的,其他一切都是通过琐碎的+1 -1更正获得的:

  • 甲。 (min, max) = [min + 1, max),因此我们从B.获得 min + 1 + Math.floor(Math.random() * (max - min - 1))
  • B中。 min + Math.floor(Math.random() * (max - min))
  • ℃。由于在区间算术(min, max] = max - [0, max - min)中,也可以编写max - Math.floor(Math.random() * (max - min))
  • d。因此[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),是的。

  • C:max - Math.random() * (max - min),与上述对称。
  • D:无法保证我们曾经达到上限区间,所以我们可以使用min + Math.random() * (max - min)

A和D之间的区别如下:如果我们尝试在A中使用公式min + Math.random() * (max - min),我们偶尔会得到0(因为可能的数字范围实际上是有限的)。但是,没有合理的统计数据可能会抱怨D的上限没有被击中。

答案 1 :(得分:0)

整数:

  • A:return Math.floor(Math.random() * (max - min - 1)) + min + 1;
  • B:正确
  • C:这与[min + 1,max + 1]相同,所以:return Math.floor(Math.random() * (max - min)) + min + 1;
  • D:正确

对于浮点数,您需要知道您拥有什么样的浮点运算。除非你使用特殊的库,否则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;
}

然后是整数

  • 答:返回nextInt(min + 1,max);
  • B:返回nextInt(min,max);
  • C:返回nextInt(min + 1,max + 1);
  • D:返回nextInt(min,max + 1);

花车是一个更复杂的案例。有些人可能会争辩说,是否包含终点并没有多大区别 - 特别是可以使用开放式解决方案而不是封闭 - 因为终点很少被选中。但由于完全有可能实现所有场景,我认为对如何实现它有数学兴趣。

答:在这种情况下,我们可以简单地确保再次滚动非法值:

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的精确实现中应该注意的一个小问题。函数的调用者可能会使用相邻的浮点调用它。通过对参数的任何虚拟检查都不容易看到,因此为了安全起见,应该限制循环执行的次数。