JavaScript随机数

时间:2013-07-07 21:53:13

标签: javascript math

这可能是比编程更多的数学问题。在JS我想要一个函数,在一个区间中返回一个随机整数,让我们说1-6,这就是我发现的:

// Returns a random integer between min and max
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

如果我将其复制并粘贴到我的代码中,我会感到内疚。我不明白这个: 为什么我们从max中减去min,加1,将答案乘以Math.random()然后加上min。我手动在纸上累了几个数字,它工作得很好!但我不明白为什么!

4 个答案:

答案 0 :(得分:5)

假设您已经了解Math.floorMath.random的行为,请按照以下步骤进行操作:

  • Math.random()0(含)与1之间的随机数(不包括)
  • Math.random() * max0(含)与max之间的随机数(不包括)
  • Math.floor(Math.random() * max) {0(包括)和max之间的随机整数(不包括在内)
  • Math.floor(Math.random() * (max - min)) + min {min(包括)和max之间的随机整数(不包括在内)
  • Math.floor(Math.random() * ((max + 1) - min)) + minmin(包括)和max+1之间的随机整数(不包括)(min与{{之间的 OR 1}}包括两者)

答案 1 :(得分:3)

Math.random()将为您提供0到1之间的“真实”数字(不包括1.0)。

这很酷,但是如果我想要一个从1到2的“真实”数字呢?

答案:将你的[0,1]“转换”为[1,2]。

实际上,这意味着在结果中添加1。

尝试一下 - Math.random()+1将为您提供1到2的数字。

在数学中,这被称为“映射”。也就是说 - 对于[0,1]中的每个可能的实数,找到一种方法将实数“映射”到[1,2]中的另一个实数。也就是说,如果我在[0,1]之间给你任何实数,你应该能够映射该数字 - 将该数字应用于将在[1,2]之间返回数字的函数。

在我们的例子中,函数f(x)= x + 1。

你看到这给我们在[1,2]之间的随机数吗?可视化彼此相邻的两个间隔,并想象一条线从[0,1)中的每个点到[1,2]中的相应地图。现在,在[0,1)上选择一个随机点...并按照该行。你将跟随[1,2]中的随机点!

现在,从[0,1)到[1,2]的所有完整的一对一映射都会将[0,1]之间的随机数转换为[1,2]之间的随机数...但是并非所有这些都会在[1,2]之间给出均匀分布的随机数。数据背后的数据给出了均匀分布的结果有点复杂但简而言之,如果你的地图只涉及加,减,乘和除以常数,那么结果也是均匀分布的意义上它是“合法的”。

所以,现在我们知道如何将[0,1]转换为[1,2]。

如果我想将[0,1]映射到[0,2]怎么办?我不能再添加数字......

我把所有东西乘以两个怎么样?

这应该有效 - 函数f(x)= x * 2确实将[0,1)上的每个点映射到[0,2)上的一个点上,因为它只涉及乘以常数( 2),它是一个保持分布的地图。

这个有效! Math.random()*2将为您提供0到2之间的随机数。

好的,现在有点复杂了......将[0,1]转换为[1,3]。

乘以2不起作用... 0 * 2 = 0,并且不在您的目标范围内。 添加一个不起作用...即使0 + 1在你的目标范围内,1 + 1也是如此,你也无法达到3。

如果我们不能将[0,1]转换为[1,3],那么让我们试着看看我们是否可以将其他东西转换成[1,3]。

[0,2]怎么样?是的,我们可以这样做...函数f(x)= x + 1完美地映射[0,2]到[1,3]。您可以将+视为“移动”范围。

所以这里的解决方案是明确的 - 首先,将[0,1]变为[0,2],然后将[0,2]变为[1,3]。

我们已经知道第一个(f(x)= x * 2),我们计算出第二个(f(x)= x + 1)。所以“组合”变换/映射是f(x)=(x * 2)+1。

也就是说,Math.random()*2 + 1将为您提供0到3之间的数字。

现在进行最后一招......将[0,1]映射到任意范围[min,max]。

这里的秘诀是将其重写为[min,min + range],其中range = max-min。

在这里你可以看到将范围[0,范围]转换为[min,min + range]很简单 - 只需添加“min”即可。所以,如果我有[0,范围]范围,并且我想获得[min,min + range],我会使用f(x)= x + min。

那么我们如何从[0,1)到[0,范围]?

乘以范围!

f(x)=(x *范围)+ min

现在使用range = max-min

将内容写回原始术语

f(x)=(x *(max-min))+ min

会将[0,1]中的实数从[min,max]

转换为实数

我会把剩下的(把它变成一个有用的整数)留给你

答案 2 :(得分:1)

以下是对您的代码的解释:

  • Math.random()生成0到1之间的随机数(不包括1)。
  • 您需要根据所需的数字范围缩放该值。您的范围是min所需数字与max所需数字max - min的距离。
  • 如果您想在生成的数字范围中包含max值,请使用max - min + 1
  • 然后,您需要确保随机数从右侧开始,而不是0,因此您需要添加min
  • 然后,如果您希望它是一个整数,请调用Math.floor()将其截断为下一个最小整数。

所以,如果你刚才有这个:

Math.floor(Math.random())

你总是会得到零。因为0到1之间的浮点值的Math.floor()(不包括一个)将始终截断为0。

然后,如果您使用以下内容扩展范围:

Math.floor(Math.random() * (max - min + 1))

现在,您将获得0到max - min之间的随机数,包括更大的值。

所以,要让它从正确的基础开始,你可以像这样添加min

Math.floor(Math.random() * (max - min + 1)) + min

答案 3 :(得分:1)

0 <= Math.random() < 1  =>
0 <= Math.random() * 6 < 6 =>
0 <= Math.floor( Math.random() * 6 ) <= 5   

然后你添加'min'所以它看起来像这样:

min <= Math.floor( Math.random() * 6 ) <= 5 + min

在你的例子中,对于min = 1,你将拥有1-6中的所有数字。

我希望现在很清楚。