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


当前回答

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的标准数字类型可以表示的最大公共整数大小。(如果需要更大的范围,可以将其修改为使用BigInts。)无论选择的范围如何,生成的被拒绝值的比例始终小于0.5,因此预期的拒绝数始终小于1.0,通常接近0.0;你不必担心它会永远循环。

常量随机整数=(最小值,最大值)=>{常量范围=最大值-最小值;常量maxGeneratedValue=0xFFFFFFFF;const possibleResultValues=范围+1;const possibleGeneratedValues=最大生成值+1;常量余数=possibleGeneratedValues%possibleResultValues;const maxUnbiased=maxGeneratedValue-余数;if(!Number.isInteger(min)||!Number.isInteger(最大值)||max>Number.max_SAFE_INTEGER||min<Number.min_SAFE_INDEGER){抛出新错误(“参数必须是安全整数。”);}否则如果(范围>maxGeneratedValue){抛出新错误(`范围为${Range}(从${min}到${max})>${maxGeneratedValue}。`);}否则,如果(最大值<最小值){抛出新错误(`max(${max})必须>=min(${min})。`);}否则如果(min==max){返回最小值;} let生成;做{generated=crypto.getRandomValues(新Uint32Array(1))[0];}而(生成>maxUnbiased);return min+(生成的%possibleResultValues);};console.log(randomInteger(-8,8));//-2.console.log(randomInteger(0,0));//0console.log(随机整数(0,0xFFFFFFFF));//944450079console.log(随机整数(-1,0xFFFFFFFF));//错误:4294967296覆盖-1到4294967295的范围>4294967295。console.log(new Array(12).fill().map(n=>randomInteger(8,12)));// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]

其他回答

要获得一个介于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的原因是,仅使用最小值可以获得比最大值多1的整数。通过从最小值中减去0.5,基本上防止了最大值被舍入。

Use:

<!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。这段代码很短。

下面是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;
}());

Use:

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

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

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

加密功能强

要获取[x,y]范围内的加密强随机整数,请尝试:

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