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

Javascript 在指定范围内生成随机数-各种情况(int、float、inclusive、exclusive),javascript,random,floating-point,integer,range,Javascript,Random,Floating Point,Integer,Range,给定一个Math.random()函数,该函数返回一个介于[0,1)和minmax值之间的数字来指定范围,我们如何为以下情况生成数字: 需要整数的情况下: A:(最小值,最大值)? B:[min,max]返回Math.floor(Math.random()*(max-min))+min; C:(最小值,最大值)? D:[min,max]返回Math.floor(Math.random()*(max-min+1))+min; 我们想要浮动的情况下: A:(最小值,最大值)? B:[min,m

给定一个
Math.random()
函数,该函数返回一个介于[0,1)和
min
max
值之间的数字来指定范围,我们如何为以下情况生成数字:

需要整数的情况下:

  • A:(最小值,最大值)?
  • B:[min,max]返回Math.floor(Math.random()*(max-min))+min;
  • C:(最小值,最大值)?
  • D:[min,max]返回Math.floor(Math.random()*(max-min+1))+min;
我们想要浮动的情况下:

  • A:(最小值,最大值)?
  • B:[min,max)返回Math.random()*(max-min)+min;
  • C:(最小值,最大值)?
  • D:[最小值,最大值]?
整数:

  • 答:
    返回Math.floor(Math.random()*(max-min-1))+min+1;
  • B:对
  • C:这与[min+1,max+1]相同,因此:
    返回Math.floor(Math.random()*(max-min))+min+1;
  • D:对
对于浮点运算,您需要知道您拥有哪种浮点运算。除非您使用特殊的库,否则浮点运算中的相等通常不会发生,因此具有闭合范围没有任何实际意义。因此,这四种运算之间应该没有区别,您可以使用:

返回Math.random()*(max-min)+min;

为了使问题有意义,您需要定义一个最小可接受的相等范围(例如
r=0.0000000000000000 1
)。然后您可以将开放范围方程(即
(min,max)
)转换为
[min+r,max-r]
整数 你的B.公式是正确的,其他的都是通过简单的
+1
-1
修正得到的:

  • A.
    (最小,最大)=[min+1,最大)
    ,因此从B.我们获得
    min+1+Math.floor(Math.random()*(max-min-1))
  • B.
    min+Math.floor(Math.random()*(max-min))
  • C.由于在区间算术中
    (min,max]=max-[0,max-min)
    ,因此也可以编写
    max-Math.floor(Math.random()*(max-min))
  • 因此:
    min+Math.floor(Math.random()*(max+1-min))

<强>浮点.V13已经指出,这个问题有点不适定:如果我们把单点当作度量零点集,则几乎(在理论上意义上)这四个集合之间没有差别……但是,如果你想保证排除的间隔边界永远不会(不只是“几乎从不”)采样后,如果假设没有舍入错误,可以执行以下操作:

  • 答:
    var middle=(min+max)/2;var sign=Math.random()>0.5?1:-1;返回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中没有达到上限。

我将首先定义接下来的两个帮助函数,然后使用它们来获取值。这些方法是您对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;
}
然后对于整数

  • A:返回下一个(最小值+1,最大值)
  • B:返回下一个(最小值、最大值)
  • C:返回nextInt(最小值+1,最大值+1)
  • D:返回下一个(最小值,最大值+1)
浮动是一种更复杂的情况。有些人可能会争辩说,是否包含端点没有太大区别——特别是可以使用开放式解决方案而不是封闭式解决方案,因为端点很少被选择。但由于完全有可能实现所有场景,我认为这是数学问题对如何做到这一点缺乏兴趣

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

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中max的可能性-如果参考函数完全一致(通常不一致),则该值的概率比任何其他值都稍高,但通常这只是一个理论问题。(准确地说,如果该范围内有n个可能值,则最大值pmax=1/(n-1)的概率和任何其他值的概率为(1-pmax)/(n-1))

应该注意在精确实现浮点情况A时应注意的一个小问题。函数的调用方可能会使用相邻的浮点调用它。通过对参数的任何伪检查都不容易看出这一点,因此为了安全起见,应该对循环ma的次数进行限制y将被执行。

我的参考来自您的
float B