ChatGPT解决这个技术问题 Extra ChatGPT

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

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

这是一个有用的要点:gist.github.com/kerimdzhanov/7529623
附带说明:对于那些使用 npm 并寻找快速、可靠和现成的解决方案的人来说,lodash.random 可以很容易地使用,而且占用空间极小(它只会导入方法本身,而不是整个 lodash)。
您能explicit回答关于数字范围的问题吗?特别是零。负数呢? ("Texts that从自然数中排除零有时指的是 自然数和零一起 作为整数"< /i>)。 (但没有“编辑:”、“更新:”或类似的 - 问题应该看起来好像是今天写的。)
这里的许多答案都回答了一些不同的问题(它们不是真正的答案)。这就像一些用户只阅读“生成随机整数”而从未进入“特定范围”部分(甚至是 [4; 8] 示例的正文)。

u
user229044

Mozilla Developer Network 页面上有一些示例:

/**
 * 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() 返回介于 0(包括)和 1(不包括)之间的 Number。所以我们有一个这样的间隔:

[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 的第一个功能。第二个,返回一个介于 minmax 之间的整数,两者都包括在内。

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

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

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()-1,因为 max 现在滚动的机会稍少,但您也可以滚动(不需要的)min-1 结果。


它这样做只是因为它调用了 floor,它向下取整。
@thezachperson31 您可以使用 round,但是 minmax 都只有一半的机会像其他数字一样滚动。您也可以减去一个并取 ceil。然而,由于 [0,1) 间隔,这使得 max 数字滚动的机会最小。
如果有人想测试此方法的分布,我创建了一个 JSFiddle:jsfiddle.net/F9UTG/1
@JackFrost 是的,没错。你不傻,你只是在学习:)
这个问题很老,但是理解这个答案让我花了太多时间哦,我认为在下一个 JavaScript 版本上扩展 math.random 会很有用
D
Darin Dimitrov
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;

我知道这是一个非常古老的答案,但使用 (Math.random() * (maximum - minimum + 1) ) << 0 更快。
@IsmaelMiguel 使用二元运算符(x << 0x | 0~~x)而不是 Math.floor()x 转换为范围比 Number.MAX_SAFE_INTEGER 小得多的二补码(2³²⁻¹ vs. 2⁵³),因此你必须谨慎使用它!
@IsmaelMiguel 哟,我刚刚在控制台中尝试了你的方法,随机得到一个负值! Math.randRange = (最小值,最大值) => (Math.random() * (最大值 - 最小值 + 1) ) << 0 Math.randRange(2,657348096152) -1407373159
@bluejayke因为657348096152(二进制1001100100001100111111111111000010011000)有40位,而按位算术使用32位。如果你执行 657348096152|0,你会得到 218099864(二进制的 1100111111111111000010011000)。
这是一个聪明的答案。使范围在内部 [min, max+1) 实际上实现了 [min, max] 包含两者的期望结果。谢谢! :)
C
Community

数学随机()

返回介于 min (included) 和 max (included) 之间的 integer random number

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

或在最小值(包括)和最大值(不包括)之间的any random number

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 可以省掉
P
Peter Mortensen

利用:

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.
}

分解:

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

('bottom' 是较小的数字,而 'top' 是较大的数字)

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

Math.random() 返回 0 和 1 之间的随机双精度数,如果我们将它乘以 1 加上 topbottom 之间的差,我们将在 01+b-a 之间的某处得到一个双精度数。

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

Math.floor 将数字向下舍入到最接近的整数。所以我们现在有了 0top-bottom 之间的所有整数。 1 看起来令人困惑,但它必须存在,因为我们总是向下舍入,所以如果没有它,将永远无法真正达到最高数字。我们生成的随机小数需要在 0(1+top-bottom) 范围内,因此我们可以向下舍入并获得 0top-bottom 范围内的整数:

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

上一个示例中的代码为我们提供了 0top-bottom 范围内的整数,因此我们现在需要做的就是将 bottom 添加到该结果中以获取范围 bottomtop 内的整数包括的。 :D

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


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

所有这些解决方案都使用了太多的火力。您只需要调用一个函数:Math.random();

Math.random() * max | 0;

这将返回 0(包括)和 max(不包括)之间的随机整数。


这太干净了。谢谢!
OP 询问的是 4 和 8 之间的范围,而不是 8 和 0
然后它不起作用。 Math.random() * 10 | 5 仅输出 5 | 7 | 13
当心:这个答案不可靠。最大值:5 和最小值:1 返回:1、3、5。
答案没有错。人们显然不知道 | 位或运算符的作用。如前所述,此解决方案适用于下限 0 和非包含上限 max 之间的数字。
n
nbro

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

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

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

Math.floor((Math.random()*100) + 1)

你的“之间”是包容的还是排斥的?即是 [1,10]、[1,10)、(1,10] 还是 (1,10)?
它是部分包含的:[1, *)
函数末尾需要 + 1 是什么?我猜它工作得很好。
@Shachi:这是下限(一个选择不当的例子)。 4,如题,会更好。
1太特别了。这将分解为其他数字,例如问题中的 4 和 8(范围将(大约)是 [4;12],而不是 [4;8])。
C
Codler
function randomRange(min, max) {
  return ~~(Math.random() * (max - min + 1)) + min
}

如果您使用的是 Underscore.js 替代方案,您可以使用

_.random(min, max)

Underscore 实际上提供了一个 _.uniqueId() 函数,您可以为客户端模型调用该函数。
使用二元运算符(x << 0x | 0~~x)而不是 Math.floor()x 转换为范围比 Number.MAX_SAFE_INTEGER 小得多的二补码(2³²⁻¹ 与 2⁵³),因此您有谨慎使用!
P
Peter Mortensen

如果你需要一个介于 0 和最大值之间的变量,你可以使用:

Math.floor(Math.random() *  max);

max 是包容性的还是独占性的>?
@Tree 使用 Math.floor max 是唯一的。如果您希望 max 具有包容性,您可以使用 Math.round。
像这里的许多其他答案一样,这并没有回答问题(我的重点):“我如何生成随机整数 在两个指定变量之间 在 JavaScript 中,例如 x = 4 和 y = 8 将输出 4、5、6、7、8 中的任何一个?"。换言之,指定 range/closed interval 中的随机数(示例中为 [4; 8])。甚至标题都说“在特定范围内”。这属于评论。
S
Starkers

其他答案没有考虑 01 的完全合理的参数。相反,您应该使用 ceilfloorround instead

function randomNumber(minimum, maximum){
    return Math.round( Math.random() * (maximum - minimum) + minimum);
}

console.log(randomNumber(0,1));  # 0 1 1 0 1 0
console.log(randomNumber(5,6));  # 5 6 6 5 5 6
console.log(randomNumber(3,-1)); # 1 3 1 -1 -1 -1

您的回答是正确的,但我认为您的示例是错误的.. console.log(randomNumber(5,6)); # 9 6 6 5 7 7 做 9 & 7 介于 5 和 5 之间6? ......你应该更正它或解释..
最后一个例子可以被认为是一个空范围。例如,无效的输入参数。结果为空、抛出错误或类似情况。
P
Peter Mortensen

密码学强

要获得 [x,y] 范围内的 cryptographically strong 随机整数,请尝试:

让 cs = (x,y) => x + (y - x + 1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32 | 0 控制台.log(cs(4, 8))


这个很迷人
我会推荐这个
我在这个问题上陷入了困境,试图了解加密安全的含义。在这里结束:crypto.stackexchange.com/questions/39186/…
+1,这是最好的!但是,我使用了 (x, y) => x + crypto.getRandomValues(new Uint32Array(1))[0] % (y - x + 1) (整数模而不是浮点除法)
是否有可能得到解释,例如何时加密强度很重要以及为什么这个答案与 Math.random() 的答案不同?
3
3 revs, 2 users 54%

使用此函数获取给定范围内的随机数:

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

这与以前的答案有何不同?
P
Peter Mortensen

这是 JavaScript 中 Random 类的 Microsoft .NET 实现——

var Random = (function () {
    function Random(Seed) {
        if (!Seed) {
            Seed = this.milliseconds();
        }
        this.SeedArray = [];
        for (var i = 0; i < 56; i++)
            this.SeedArray.push(0);
        var num = (Seed == -2147483648) ? 2147483647 : Math.abs(Seed);
        var num2 = 161803398 - num;
        this.SeedArray[55] = num2;
        var num3 = 1;
        for (var i_1 = 1; i_1 < 55; i_1++) {
            var num4 = 21 * i_1 % 55;
            this.SeedArray[num4] = num3;
            num3 = num2 - num3;
            if (num3 < 0) {
                num3 += 2147483647;
            }
            num2 = this.SeedArray[num4];
        }
        for (var j = 1; j < 5; j++) {
            for (var k = 1; k < 56; k++) {
                this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55];
                if (this.SeedArray[k] < 0) {
                    this.SeedArray[k] += 2147483647;
                }
            }
        }
        this.inext = 0;
        this.inextp = 21;
        Seed = 1;
    }

    Random.prototype.milliseconds = function () {
        var str = new Date().valueOf().toString();
        return parseInt(str.substr(str.length - 6));
    };

    Random.prototype.InternalSample = function () {
        var num = this.inext;
        var num2 = this.inextp;
        if (++num >= 56) {
            num = 1;
        }
        if (++num2 >= 56) {
            num2 = 1;
        }
        var num3 = this.SeedArray[num] - this.SeedArray[num2];
        if (num3 == 2147483647) {
            num3--;
        }
        if (num3 < 0) {
            num3 += 2147483647;
        }
        this.SeedArray[num] = num3;
        this.inext = num;
        this.inextp = num2;
        return num3;
    };

    Random.prototype.Sample = function () {
        return this.InternalSample() * 4.6566128752457969E-10;
    };

    Random.prototype.GetSampleForLargeRange = function () {
        var num = this.InternalSample();
        var flag = this.InternalSample() % 2 == 0;
        if (flag) {
            num = -num;
        }
        var num2 = num;
        num2 += 2147483646.0;
        return num2 / 4294967293.0;
    };

    Random.prototype.Next = function (minValue, maxValue) {
        if (!minValue && !maxValue)
            return this.InternalSample();
        var num = maxValue - minValue;
        if (num <= 2147483647) {
            return parseInt((this.Sample() * num + minValue).toFixed(0));
        }
        return this.GetSampleForLargeRange() * num + minValue;
    };

    Random.prototype.NextDouble = function () {
        return this.Sample();
    };

    Random.prototype.NextBytes = function (buffer) {
        for (var i = 0; i < buffer.length; i++) {
            buffer[i] = this.InternalSample() % 256;
        }
    };
    return Random;
}());

利用:

var r = new Random();
var nextInt = r.Next(1, 100); // Returns an integer between range
var nextDbl = r.NextDouble(); // Returns a random decimal

MS DotNet Random 类在 Ms-RSL 许可下,这意味着它受版权保护。所以在使用这个派生代码时要小心,因为它可能成为侵犯版权案件的基础。
T
Travis

这是我用来生成随机数的方法。

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

Math.random() 返回一个介于 0(包括)和 1(不包括)之间的数字。我们将此数字乘以范围(最大-最小)。这会产生一个介于 0(含)和范围之间的数字。

例如,以 random(2,5)0 为例。我们将随机数 0≤x<1 乘以范围 (5-2=3),所以我们现在有一个数 x,其中 0≤x<3。

为了强制函数将最大值和最小值都视为包含值,我们将范围计算加 1:Math.random()*(max-min+1)。现在,我们将随机数乘以 (5-2+1=4),得到一个数 x,使得 0≤x<4。如果我们对这个计算求底,我们会得到一个整数:0≤x≤3,每个结果的可能性相等 (1/4)。

最后,我们需要将其转换为请求值之间的整数。由于我们已经有一个介于 0 和 (max-min) 之间的整数,我们可以通过添加最小值简单地将值映射到正确的范围内。在我们的示例中,我们将 0 到 3 之间的整数加 2,得到 2 到 5 之间的整数。


由于 high 只使用一次,您不妨使用 high-low+1 而不是单独的增量语句。此外,大多数用户都希望 low 参数排在第一位。
random(2,5)0 似乎无效。
@PeterMortensen 语法错误。随机(2,5)工作正常。 0 有什么用?
P
Peter Mortensen

使用计算机程序生成随机数后,如果选择的数字是初始数字的一部分或全部,则仍将其视为随机数。但是如果它被改变了,那么数学家就不会接受它是一个随机数,他们可以称之为有偏数。

但是,如果您正在为一项简单的任务开发程序,则不需要考虑这种情况。但是,如果您正在开发一个程序来为彩票程序或赌博游戏等有价值的东西生成随机数,那么如果您不考虑上述情况,您的程序将被管理层拒绝。

所以对于这样的人,我的建议是:

使用 Math.random() 生成一个随机数(比如这个 n):

Now for [0,10) ==>  n*10 (i.e. one digit) and for[10,100) ==> n*100 (i.e., two digits) and so on. Here square bracket indicates that the boundary is inclusive and a round bracket indicates the boundary is exclusive.

然后删除小数点后的其余部分。 (即,获得发言权) - 使用 Math.floor()。这是可以做到的。

如果你知道如何阅读随机数表来选择一个随机数,你就知道上面的过程(乘以 1、10、100 等等)并不违反我一开始提到的那个(因为它只会改变小数点的位置)。

研究以下示例并根据您的需要进行开发。

如果您需要样本 [0,9],那么 n10 的下限就是您的答案,如果您需要 [0,99],那么 n100 的下限就是您的答案,依此类推。

现在让我们进入你的角色:

您要求提供特定范围内的数字。 (在这种情况下,您会偏向于该范围。通过掷骰子从 [1,6] 中取一个数字,然后您会偏向 [1,6],但当且仅当骰子时,它仍然是一个随机数是公正的。)

所以考虑你的范围 ==> [78, 247] 范围的元素数 = 247 - 78 + 1 = 170; (因为两个边界都包含在内)。

/* Method 1: */
    var i = 78, j = 247, k = 170, a = [], b = [], c, d, e, f, l = 0;
    for(; i <= j; i++){ a.push(i); }
    while(l < 170){
        c = Math.random()*100; c = Math.floor(c);
        d = Math.random()*100; d = Math.floor(d);
        b.push(a[c]); e = c + d;
        if((b.length != k) && (e < k)){  b.push(a[e]); }
        l = b.length;
    }
    console.log('Method 1:');
    console.log(b);

/* Method 2: */

    var a, b, c, d = [], l = 0;
    while(l < 170){
        a = Math.random()*100; a = Math.floor(a);
        b = Math.random()*100; b = Math.floor(b);
        c = a + b;
        if(c <= 247 || c >= 78){ d.push(c); }else{ d.push(a); }
        l = d.length;
    }
    console.log('Method 2:');
    console.log(d);

注意:在方法一中,首先我创建了一个包含您需要的数字的数组,然后将它们随机放入另一个数组中。

在方法二中,随机生成数字并检查它们是否在您需要的范围内。然后将其放入数组中。在这里,我生成了两个随机数,并使用它们的总和通过最小化获得有用数字的失败率来最大化程序的速度。但是,添加生成的数字也会产生一些偏差。所以我会推荐我的第一种方法来生成特定范围内的随机数。

在这两种方法中,您的控制台都会显示结果(按 Chrome 中的 F12 打开控制台)。


“随机”并不一定意味着“均匀分布”。 “有偏见”并不意味着“非随机”。从概率分布中抽取的随机均值。
几乎无法说出这个答案想说什么。但是,如果您需要随机数用于彩票号码和赌博等用途。首先,您可能不应该在客户端上生成它们。其次,您需要一个加密安全的随机数生成器,而提供的算法是不够的。反复调用 random 不会使结果“更随机”。作者似乎担心偏见,但没有提供防止偏见的好算法。事实上,提供的其他简短答案会产生无偏随机数(假设底层随机生成器是无偏的)。
@JeffWalkerCodeRanger 我认为他的意思是,使用“正常”算法 [即 Math.floor(Math.random() * (6 - 1 + 1) + 1)],数字 1 和 6 的滚动次数必然少于 2、3、4 和 5。但是,差异基本上是微不足道的。
P
Peter Mortensen

我想用一个例子来解释:

在 JavaScript 中生成 5 到 25 范围内的随机整数的函数

一般概述:(i)首先将其转换为范围 - 从 0 开始。(ii)然后将其转换为您想要的范围(这将很容易完成)。

所以基本上,如果你想生成从 5 到 25 的随机整数,那么:

第一步:将其转换为范围 - 从 0 开始

从“max”和“min”中减去“lower/minimum number”。 IE

(5-5) - (25-5)

所以范围将是:

0-20 ...对吗?

第二步

现在,如果您希望两个数字都包含在范围内 - 即“0 和 20”,则等式将是:

数学方程:Math.floor((Math.random() * 21))

一般方程:Math.floor((Math.random() * (max-min +1)))

现在,如果我们将减数/最小数(即 5)添加到该范围 - 那么我们可以自动获得从 0 到 20 => 5 到 25 的范围

第三步

现在添加您在等式中减去的差(即 5)并将“Math.floor”添加到整个等式:

数学方程:Math.floor((Math.random() * 21) + 5)

一般方程:Math.floor((Math.random() * (max-min +1)) + min)

所以最后的功能将是:

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

C
Chris
function getRandomInt(lower, upper)
{
    //to create an even sample distribution
    return Math.floor(lower + (Math.random() * (upper - lower + 1)));

    //to produce an uneven sample distribution
    //return Math.round(lower + (Math.random() * (upper - lower)));

    //to exclude the max value from the possible values
    //return Math.floor(lower + (Math.random() * (upper - lower)));
}

要测试此功能以及此功能的变体,请将以下 HTML/JavaScript 保存到文件并使用浏览器打开。该代码将生成一个图表,显示一百万个函数调用的分布。该代码还将记录边缘情况,因此如果该函数产生的值大于最大值或小于最小值,you.will.know.about.it。

<html>
    <head>
        <script type="text/javascript">
        function getRandomInt(lower, upper)
        {
            //to create an even sample distribution
            return Math.floor(lower + (Math.random() * (upper - lower + 1)));

            //to produce an uneven sample distribution
            //return Math.round(lower + (Math.random() * (upper - lower)));

            //to exclude the max value from the possible values
            //return Math.floor(lower + (Math.random() * (upper - lower)));
        }

        var min = -5;
        var max = 5;

        var array = new Array();

        for(var i = 0; i <= (max - min) + 2; i++) {
          array.push(0);
        }

        for(var i = 0; i < 1000000; i++) {
            var random = getRandomInt(min, max);
            array[random - min + 1]++;
        }

        var maxSample = 0;
        for(var i = 0; i < max - min; i++) {
            maxSample = Math.max(maxSample, array[i]);
        }

        //create a bar graph to show the sample distribution
        var maxHeight = 500;
        for(var i = 0; i <= (max - min) + 2; i++) {
            var sampleHeight = (array[i]/maxSample) * maxHeight;

            document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px">&nbsp;[' + (i + min - 1) + ']:&nbsp;'+array[i]+'</span>&nbsp;&nbsp;');
        }
        document.write('<hr/>');
        </script>
    </head>
    <body>

    </body>
</html>

n
nbro

对于具有范围的随机整数,请尝试:

function random(minimum, maximum) {
  var bool = true;

  while (bool) {
    var number = (Math.floor(Math.random() * maximum + 1) + minimum);
    if (number > 20) {
      bool = true;
    } else {
      bool = false;
    }
  }

  return number;
}

P
Peter Mortensen

要获得一个介于 1 和 6 之间的随机数,请首先执行以下操作:

0.5 + (Math.random() * ((6 - 1) + 1))

这将一个随机数乘以 6,然后再加上 0.5。接下来通过执行以下操作将数字四舍五入为正整数:

Math.round(0.5 + (Math.random() * ((6 - 1) + 1))

这会将数字四舍五入到最接近的整数。

或者为了让它更容易理解,这样做:

var value = 0.5 + (Math.random() * ((6 - 1) + 1))
var roll = Math.round(value);
return roll;

通常,使用变量执行此操作的代码是:

var value = (Min - 0.5) + (Math.random() * ((Max - Min) + 1))
var roll = Math.round(value);
return roll;

从最小值中减去 0.5 的原因是因为单独使用最小值将允许您获得比最大值大一的整数。通过从最小值中减去 0.5,您实际上是在防止最大值被四舍五入。


如果您排除 0 是有道理的,那么无需将 0 到 0.5 的范围“向下舍入”。
P
Peter Mortensen

使用以下代码,您可以在给定范围内生成一个不重复的随机数数组。

function genRandomNumber(how_many_numbers, min, max) {

    // Parameters
    //
    //   how_many_numbers: How many numbers you want to
    //                     generate. For example, it is 5.
    //
    //   min (inclusive):  Minimum/low value of a range. It
    //                     must be any positive integer, but
    //                     less than max. I.e., 4.
    //
    //   max (inclusive):  Maximum value of a range. it must
    //                     be any positive integer. I.e., 50
    //
    //   Return type: array

    var random_number = [];
    for (var i = 0; i < how_many_numbers; i++) {
        var gen_num = parseInt((Math.random() * (max-min+1)) + min);
        do {
            var is_exist = random_number.indexOf(gen_num);
            if (is_exist >= 0) {
                gen_num = parseInt((Math.random() * (max-min+1)) + min);
            }
            else {
                random_number.push(gen_num);
                is_exist = -2;
            }
        }
        while (is_exist > -1);
    }
    document.getElementById('box').innerHTML = random_number;
}

P
Peter Mortensen

最低和最高之间的随机整数:

function randomRange(low, high) {
  var range = (high-low);
  var random = Math.floor(Math.random()*range);
  if (random === 0) {
    random += 1;
  }
  return low + random;
}

这不是最优雅的解决方案,但很快。


+=”中的“+”似乎是多余的。 (high-low) 中的括号似乎是多余的。
考虑到特殊情况(if),关于随机数的分布可以说什么?
P
Peter Mortensen

我在 W3Schools 上找到了这个简单的方法:

Math.floor((Math.random() * max) + min);

Math.floor((Math.random() * 1) + 0);总是给 0
@madprops 因为最大数量是排他的。要获得 0 或 1,您应该将 2 设置为最大数。
或者您只需在调用此方法的函数中添加 + 1
你是在哪里找到那个东西的。这不会在范围内输出 [min;最大限度]。例如,如果 min = 3000 和 max = 7000,它将(大约)输出范围为 [3000; 10000](不是 [3000; 7000])。
J
Jeremy

Math.random() 速度快且适用于多种用途,但如果您需要加密安全的值(它不安全),或者如果您需要来自完全统一的无偏分布的整数(其他答案中使用的乘法方法会产生某些值),则不适合比其他人更频繁)。

在这种情况下,我们可以使用 crypto.getRandomValues() 生成安全整数,并拒绝任何我们无法统一映射到目标范围的生成值。这会更慢,但它不应该很重要,除非您生成大量的值。

为了澄清有偏差的分布问题,考虑我们想要生成 1 到 5 之间的值的情况,但我们有一个随机数生成器生成 1 到 16 之间的值(一个 4 位值)。我们希望将相同数量的生成值映射到每个输出值,但是 16 不能除以 5:它留下余数 1。因此我们需要拒绝可能生成的值中的 1 个,只有在得到时才继续可以统一映射到我们的目标范围的 15 个较小值之一。我们的行为可能看起来像这样的伪代码:

Generate a 4-bit integer in the range 1-16.
If we generated  1,  6, or 11 then output 1.
If we generated  2,  7, or 12 then output 2.
If we generated  3,  8, or 13 then output 3.
If we generated  4,  9, or 14 then output 4.
If we generated  5, 10, or 15 then output 5.
If we generated 16 then reject it and try again.

以下代码使用类似的逻辑,但生成一个 32 位整数,因为这是 JavaScript 的标准 number 类型可以表示的最大常见整数大小。 (如果您需要更大的范围,可以将其修改为使用 BigInt。)无论选择的范围如何,被拒绝的生成值的比例总是小于 0.5,因此预期的拒绝数总是更少大于 1.0,通常接近 0.0;你不必担心它会永远循环。

const randomInteger = (min, max) => { const range = max - min;常量 maxGeneratedValue = 0xFFFFFFFF;常量可能结果值 = 范围 + 1;常量可能生成值 = 最大生成值 + 1; const 余数 = possibleGeneratedValues % possibleResultValues; const maxUnbiased = maxGeneratedValue - 余数; if (!Number.isInteger(min) || !Number.isInteger(max) || max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) { throw new Error('参数必须是安全整数。'); } else if (range > maxGeneratedValue) { throw new Error(`Range of ${range} (from ${min} to ${max}) > ${maxGeneratedValue}.`); } else if (max < min) { throw new Error(`max (${max}) must be >= min (${min}).`); } else if (min === max) { return min; } 让生成;做 { 生成 = crypto.getRandomValues(new Uint32Array(1))[0]; } 而(生成 > maxUnbiased); return min + (生成的 % possibleResultValues); }; console.log(randomInteger(-8, 8)); // -2 console.log(randomInteger(0, 0)); // 0 console.log(randomInteger(0, 0xFFFFFFFF)); // 944450079 console.log(randomInteger(-1, 0xFFFFFFFF)); // 错误:从 -1 到 4294967295 的 4294967296 范围 > 4294967295。console.log(new Array(12).fill().map(n => randomInteger(8, 12))); // [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]


crypto.getRandomValues(在此使用)和 Crypto.getRandomValues 之间有区别吗?
P
Peter Mortensen

下面是一个 JavaScript 函数示例,它可以在不使用 Math.random() 的情况下生成任意指定长度的随机数:

function genRandom(length)
{
  const t1 = new Date().getMilliseconds();
  var min = "1", max = "9";
  var result;
  var numLength = length;
  if (numLength != 0)
  {
     for (var i = 1; i < numLength; i++)
     {
        min = min.toString() + "0";
        max = max.toString() + "9";
     }
  }
  else
  {
     min = 0;
     max = 0;
     return;
  }

  for (var i = min; i <= max; i++)
  {
       // Empty Loop
  }

  const t2 = new Date().getMilliseconds();
  console.log(t2);
  result = ((max - min)*t1)/t2;
  console.log(result);
  return result;
}

t1/t2 总是非常接近 1。因此,当重复调用函数时,您的函数返回相同的数字 .. jsbin.com/xogufacera/edit?js,console
检查jsbin url ..你会自己看到输出
当长度在 4-10 之间时效果很好(正如我在我的机器上测试过的那样),因为常数 T1 和 T2 的值应该有适当的距离。
一个解释将是有序的。例如,时间的作用是什么(计时器/当前日期时间?)?想法/要点是什么?空循环的目的是什么?为了获得一些时间过去?什么是示例输出?来自 the Help Center“...总是解释为什么你提出的解决方案是合适的以及它是如何工作的”。请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen

利用:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    </head>

    <body>
        <script>
            /*
                Assuming that window.crypto.getRandomValues
                is available, the real range would be from
                0 to 1,998 instead of 0 to 2,000.

                See the JavaScript documentation
                for an explanation:

                  https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
            */
            var array = new Uint8Array(2);
            window.crypto.getRandomValues(array);
            console.log(array[0] + array[1]);
        </script>
    </body>
</html>

Uint8Array 创建一个数组,其中填充最多三位数字,最大为 999。此代码非常短。


(“Uint8Array”的语法高亮真的很奇怪。)
一个解释将是有序的。例如,想法/要点是什么?这个 window.crypto 是什么东西?为什么要嵌入到网页中?它可以在 Node.js 下工作吗?来自the Help Center“...总是解释为什么你提出的解决方案是合适的以及它是如何工作的”。请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。
像这里的许多其他答案一样,这并不能回答这个问题。它回答了其他一些问题——(我的重点)“如何在 JavaScript 中生成随机整数 在两个指定变量之间 ,例如x = 4 和 y = 8 将输出 4、5、6、7、8 中的任何一个?"。换言之,指定 range/closed interval 中的随机数(示例中为 [4; 8])。甚至标题都说“在特定范围内”
P
Peter Mortensen

这是我对一个范围内的随机数的看法,因为我想获得一个从基数到指数范围内的随机数。例如,base = 10,exponent = 2,给出一个从 0 到 100 的随机数,理想情况下,依此类推。

如果它有助于使用它,这里是:

// Get random number within provided base + exponent
// By Goran Biljetina --> 2012

function isEmpty(value) {
    return (typeof value === "undefined" || value === null);
}

var numSeq = new Array();

function add(num, seq) {
    var toAdd = new Object();
    toAdd.num = num;
    toAdd.seq = seq;
    numSeq[numSeq.length] = toAdd;
}

function fillNumSeq (num, seq) {
    var n;
    for(i=0; i<=seq; i++) {
        n = Math.pow(num, i);
        add(n, i);
    }
}

function getRandNum(base, exp) {
    if (isEmpty(base)) {
        console.log("Specify value for base parameter");
    }
    if (isEmpty(exp)) {
        console.log("Specify value for exponent parameter");
    }

    fillNumSeq(base, exp);

    var emax;
    var eseq;
    var nseed;
    var nspan;
    emax = (numSeq.length);
    eseq = Math.floor(Math.random()*emax) + 1;
    nseed = numSeq[eseq].num;
    nspan = Math.floor((Math.random())*(Math.random()*nseed)) + 1;
    return Math.floor(Math.random()*nspan) + 1;
}

console.log(getRandNum(10, 20), numSeq);

//Testing:
//getRandNum(-10, 20);
//console.log(getRandNum(-10, 20), numSeq);
//console.log(numSeq);

O
Oleg Valter is with Ukraine

这是一个在 min 和 max 之间生成随机数的函数,包括两者。

const randomInt = (max, min) => Math.round(Math.random() * (max - min)) + min;

这与以前的答案有什么不同?它有效吗?
是的,它在使用 Math.round 函数的范围内同时包含 min 和 max 。
我犯了提出多个问题的初学者错误。不止一个问题的能力根本不存在。永远不要那样做。总是,总是,总是一次一个问题。
S
Seb33300

我猜这是所有贡献中最简化的。

maxNum = 8,
minNum = 4

console.log(Math.floor(Math.random() * (maxNum - minNum) + minNum))

console.log(Math.floor(Math.random() * (8 - 4) + 4))

这会将 4 到 8 之间的随机数记录到控制台中,包括 4 和 8。


这不适用于 maxNum = 2, minNum = 1,结果始终为 1。事实上,我认为任何 min & 都一样。最多只有 1 个数字装置;下界总是结果。
P
Peter Mortensen

Ionuț G. Stan 写了 a great answer,但它对我来说有点太复杂了。因此,我在 Jason Anello 的 Math.floor( Math.random () * (max - min + 1)) + min) Explanation 中找到了对相同概念的更简单解释。

注意:在阅读 Jason 的解释之前,您应该知道的唯一重要的事情是“截断”的定义。他在描述 Math.floor() 时使用了该术语。牛津词典将“截断”定义为:

通过切断顶部或末端来缩短(某物)。


P
Peter Mortensen

一个名为 randUpTo 的函数,它接受一个数字并返回一个介于 0 和该数字之间的随机整数:

var randUpTo = function(num) {
    return Math.floor(Math.random() * (num - 1) + 0);
};

一个名为 randBetween 的函数,它接受代表一个范围的两个数字并返回这两个数字之间的一个随机整数:

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

一个名为 randFromTill 的函数,它接受代表一个范围的两个数字并返回一个介于 min(包括)和 max(不包括)之间的随机数

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

一个名为 randFromTo 的函数,它接受代表一个范围的两个数字并返回一个介于 min(包括)和 max(包括)之间的随机整数:

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

漂亮,您是否还注意到 randBetween 是(排他的)(排他的)?
P
Peter Mortensen

你可以你这个代码片段,

let randomNumber = function(first, second) {
    let number = Math.floor(Math.random()*Math.floor(second));
    while(number < first) {

        number = Math.floor(Math.random()*Math.floor(second));
    }
    return number;
}

这里有一个不必要的重复行。只需使用 do - while 而不是 while
如果 first1,000,000,000second1,000,000,042,这将非常慢。也许add对您的答案有一些警告?甚至可能有一些基准来证明性能影响何时变得重要(量化它)? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)