在 JavaScript 中生成特定范围内的随机整数?

IT技术 javascript random integer
2020-12-09 01:28:29

如何在 JavaScript 中的两个指定变量之间生成随机整数,例如x = 4y = 8输出任何一个4, 5, 6, 7, 8

6个回答

Mozilla 开发者网络页面上有一些示例

/**
 * Returns a random number between min (inclusive) and max (exclusive)
 */
function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}

/**
 * Returns a random integer between min (inclusive) and max (inclusive).
 * The value is no lower than min (or the next integer greater than min
 * if min isn't an integer) and no greater than max (or the next integer
 * lower than max if max isn't an integer).
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

这是它背后的逻辑。这是一个简单的三点规则:

Math.random()返回Number介于 0(含)和 1(不含)之间的值。所以我们有一个这样的区间:

[0 .................................... 1)

现在,我们想要一个介于min(包含)和max(不包含)之间的数字

[0 .................................... 1)
[min .................................. max)

我们可以使用Math.random来获取 [min, max) 区间内的通讯员。但是,首先我们应该通过min从第二个间隔中减去解决这个问题

[0 .................................... 1)
[min - min ............................ max - min)

这给出:

[0 .................................... 1)
[0 .................................... max - min)

我们现在可以申请Math.random然后计算通讯员。让我们选择一个随机数:

                Math.random()
                    |
[0 .................................... 1)
[0 .................................... max - min)
                    |
                    x (what we need)

所以,为了找到x,我们会这样做:

x = Math.random() * (max - min);

不要忘记加min回来,以便我们在 [min, max) 区间得到一个数字:

x = Math.random() * (max - min) + min;

这是 MDN 的第一个函数。第二个,返回一个介于min之间的整数max,两者都包括在内。

现在要获取整数,您可以使用round,ceilfloor

您可以使用Math.round(Math.random() * (max - min)) + min,但这会产生非均匀分布。两者,min并且max只有大约一半的机会滚动:

min...min+0.5...min+1...min+1.5   ...    max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘   ← Math.round()
   min          min+1                          max

max从区间中排除,它有一个甚至更少的机会比辊min

有了Math.floor(Math.random() * (max - min +1)) + min你有一个完美的均匀分布。

min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
|        |        |         |        |        |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘   ← Math.floor()
   min     min+1               max-1    max

您不能在该等式中使用ceil()and -1,因为max现在滚动的机会略少,但您也可以滚动(不需要的)min-1结果。

它这样做只是因为它正在调用floor,它会向下取整。
2021-02-08 01:28:29
这个问题很老了,但是理解这个答案花了我太多时间哦,我认为在下一个 JavaScript 版本上扩展 math.random 会很有用
2021-02-12 01:28:29
@JackFrost 是的,没错。你不笨,你只是在学习:)
2021-02-17 01:28:29
如果有人想测试此方法的分发,我已经创建了一个 JSFiddle:jsfiddle.net/F9UTG/1
2021-02-18 01:28:29
@thezachperson31 您可以使用round, 但随后两者都使用,min并且max只有一半的机会像其他数字一样滚动。你也可以减去一个并取ceil然而max,由于[0,1)间隔,这使得数字滚动的机会最小
2021-03-02 01:28:29
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
这是一个聪明的答案。在内部设置范围 [min, max+1) 实际上达到了 [min, max] 两者都包含的预期结果。谢谢!:)
2021-02-10 01:28:29
@IsmaelMiguel 使用二元运算符 ( x << 0, x | 0, ~~x) 而不是Math.floor()转换x为范围比Number.MAX_SAFE_INTEGER(2³²⁻¹ vs. 2⁵³)小得多的两个补码,因此您必须谨慎使用它!
2021-02-17 01:28:29
我知道这是一个非常古老的答案,但使用(Math.random() * (maximum - minimum + 1) ) << 0速度更快。
2021-02-22 01:28:29
@bluejayke 因为 657348096152(1001100100001100111111111111000010011000 二进制)有 40 位,而按位算术使用 32 位。如果你这样做,657348096152|0你会得到 218099864(二进制 1100111111111111000010011000)。
2021-02-22 01:28:29
@IsmaelMiguel 哟我刚刚在控制台中尝试了您的方法并随机得到了一个负值!Math.randRange = (minimum,maximum) => (Math.random() * (maximum - minimum + 1) ) << 0 Math.randRange(2,657348096152) -1407373159
2021-03-04 01:28:29

Math.random()

返回一个介于 min(包括)和 max(包括之间整数随机数

function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

min(包括)和 max(不包括之间的任何随机数

function randomNumber(min, max) {
  return Math.random() * (max - min) + min;
}

有用的例子(整数):

// 0 -> 10
Math.floor(Math.random() * 11);

// 1 -> 10
Math.floor(Math.random() * 10) + 1;

// 5 -> 20
Math.floor(Math.random() * 16) + 5;

// -10 -> (-2)
Math.floor(Math.random() * 9) - 10;

** 总是很高兴被提醒(Mozilla):

Math.random() 不提供加密安全的随机数。不要将它们用于与安全相关的任何事情。改用 Web Crypto API,更准确地说是 window.crypto.getRandomValues() 方法。

如果你拿Math.ceil,那么+1就可以幸免了
2021-02-24 01:28:29
function getRandomizer(bottom, top) {
    return function() {
        return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
    }
}

用法:

var rollDie = getRandomizer( 1, 6 );

var results = ""
for ( var i = 0; i<1000; i++ ) {
    results += rollDie() + " ";    //make a string filled with 1000 random numbers in the range 1-6.
}

分解:

我们正在返回一个函数(从函数式编程中借用),当调用该函数时,将返回值bottom之间的随机整数top,包括。我们说“包含”是因为我们希望在可以返回的数字范围内同时包含底部和顶部。这样,getRandomizer( 1, 6 )将返回 1、2、3、4、5 或 6。

(底部是较小的数字,顶部是较大的数字)

Math.random() * ( 1 + top - bottom )

Math.random()返回0和1之间的随机双,如果我们用它乘间一个加的区别topbottom,我们会得到之间的双某处01+b-a

Math.floor( Math.random() * ( 1 + top - bottom ) )

Math.floor将数字向下舍入到最接近的整数。所以我们现在有了0之间的所有整数top-bottom1 看起来令人困惑,但它需要存在,因为我们总是向下取整,因此如果没有它,实际上永远不会达到最高数字。我们生成需要随机十进制是在范围内0,以(1+top-bottom)使我们能够在范围向下取整,并得到一个int0top-bottom

Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom

在前面的例子中的代码给了我们一个整数的范围0top-bottom,所以我们现在需要做的就是添加bottom到该结果得到的整数bottomtop包容性。:D


注意:如果你先传入一个非整数值或更大的数字,你会得到不受欢迎的行为,但除非有人提出要求,否则我不会深入研究参数检查代码,因为它与原始问题的意图相去甚远.

@some,可能更糟,我 2½ 年 + 1 天后^^
2021-02-12 01:28:29
为什么你在一个函数中有一个函数呢?
2021-02-12 01:28:29
我意识到这是大约 2.5 年后,但是对于输入 1 和 6,您的函数返回值 1、2、3、4 和 5,但永远不会返回 6,就像它是“包含的”一样。
2021-02-13 01:28:29
@Alph.Dev 将使用随机数生成器的逻辑与决定使用哪种随机数分布的逻辑分离。当使用随机数生成器的代码接受它作为参数(一个始终返回新随机数的 0 参数函数)时,它可以与任何类型的随机数生成器一起使用。
2021-02-25 01:28:29
+1,我测试了你的代码,它似乎创建了一个正确的值。用于处理可能在代码中多次重复的固定场景的创造性结构。
2021-03-08 01:28:29

返回 1 到 10 之间的随机数:

Math.floor((Math.random()*10) + 1); 

返回 1 到 100 之间的随机数:

Math.floor((Math.random()*100) + 1)
函数末尾的 + 1 需要什么?我猜它完美无缺。
2021-02-18 01:28:29
你的“之间”是包容性的还是排斥性的?即它是 [1,10]、[1,10)、(1,10] 或 (1,10)?
2021-02-20 01:28:29
它是部分包容的:[1, *)
2021-03-01 01:28:29