【问题标题】:Generating random whole numbers in JavaScript in a specific range在特定范围内的 JavaScript 中生成随机整数?
【发布时间】:2010-12-04 09:50:03
【问题描述】:

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

【问题讨论】:

标签: javascript random integer


【解决方案1】:

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 是的,没错。你不傻,你只是在学习:)
  • 这个问题很老,但理解这个答案让我花了太多时间 O.o,我认为在下一个 JavaScript 版本上扩展 math.random 会很有用
【解决方案2】:
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) )
  • @bluejayke 因为 657348096152(1001100100001100111111111111000010011000 二进制)有 40 位,而按位算术使用 32 位。如果你这样做657348096152|0,你会得到 218099864(二进制的 1100111111111111000010011000)。
  • 这是一个聪明的答案。使范围在内部 [min, max+1) 实际上达到了 [min, max] 包含两者的期望结果。谢谢! :)
【解决方案3】:

Math.random()

在最小值(包含)和最大值(包含)之间返回一个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() 不提供加密安全随机 数字。不要将它们用于与安全相关的任何事情。使用网络 取而代之的是 Crypto API,更准确地说是 window.crypto.getRandomValues() 方法。

【讨论】:

  • 如果你拿Math.ceil,那么+1就可以免了
【解决方案4】:
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。

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

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

Math.random() 返回一个介于 0 和 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 添加到该结果中以获得bottom 范围内的整数和top 包括在内。 :D


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

【讨论】:

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

返回一个介于 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有什么用?我猜它工作得很好。
【解决方案6】:
function randomRange(min, max) {
  return ~~(Math.random() * (max - min + 1)) + min
}

如果您使用 Underscore.js,您可以使用替代方法

_.random(min, max)

【讨论】:

  • Underscore 实际上提供了一个_.uniqueId() 函数,您可以为客户端模型调用。
  • 使用二元运算符(x &lt;&lt; 0x | 0~~x)而不是 Math.floor()x 转换为比 Number.MAX_SAFE_INTEGER (2³²⁻¹) 范围更小的二补码vs. 2⁵³),因此您必须谨慎使用它!
【解决方案7】:

所有这些解决方案都使用了太多的火力,你只需要调用一个函数: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 之间的数字。
【解决方案8】:

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

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

【讨论】:

  • max 是包含还是独占>?
  • @Tree 使用 Math.floor max 是专有的。如果您希望 max 具有包容性,您可以使用 Math.round。
【解决方案9】:

其他答案没有考虑到01 的完全合理的参数。相反,您应该使用round 代替 ceilfloor

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 和 6 之间? ......你应该更正它或解释......
【解决方案10】:

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

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

【讨论】:

    【解决方案11】:

    加密强

    在 ragne [x,y] 中获取crypto-strong 随机整数试试

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

    【讨论】:

    • 这个很吸引人
    • 我推荐这个
    • 我在这个问题上陷入了困境,试图了解加密安全的含义。在这里结束:crypto.stackexchange.com/questions/39186/…
    • +1,这是最好的!但是,我使用了(x, y) =&gt; x + crypto.getRandomValues(new Uint32Array(1))[0] % (y - x + 1)(整数模而不是浮点除法)
    【解决方案12】:

    这是 javascript 中 Random 类的 MS DotNet 实现-

    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 许可下,这意味着它受版权保护。所以在使用这个派生代码时要小心,因为它可能会成为侵犯版权案件的基础。
    【解决方案13】:

    使用计算机程序生成随机数后,如果选择的数字是初始数字的一部分或全部,则仍将其视为随机数。但是如果它被改变了,那么数学家不会接受它作为一个随机数,他们可以称之为有偏数。但是如果你正在为一个简单的任务开发一个程序,这将不是一个案例考虑。 但如果您正在开发一个程序来为彩票程序或赌博游戏等有价值的东西生成随机数,那么如果您不考虑上述情况,您的程序将被管理层拒绝。

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

    使用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 squire bracket indicates that boundary is inclusive and round bracket indicates boundary is exclusive.
    Then remove the rest after the decimal point. (i.e. get floor) - using Math.floor(), this can be done.
    

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

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

    如果您需要样本 [0,9],则 n*10 的下限是您的答案,如果需要 [0,99],则 n*100 的下限就是您的答案,依此类推。

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

    您询问了特定范围内的数字。 (在这种情况下,您会偏向于该范围。-通过掷骰子从 [1,6] 中取一个数字,然后您会偏向 [1,6] 但当且仅当 die 无偏时它仍然是随机的.)

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

    /*Mthod 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。但是,差异基本上是微不足道的。
    【解决方案14】:

    对于一个有范围的随机整数,试试:

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

    【讨论】:

      【解决方案15】:

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

      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:Math.random()*(max-min+1)。现在,我们将随机数乘以 (5-2+1=4),得到一个数 x,使得 0≤x

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

      【讨论】:

      • 由于high 只使用一次,您不妨使用high-low+1 而不是单独的增量语句。此外,大多数用户都希望low 参数排在第一位。
      【解决方案16】:
      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>
      

      【讨论】:

        【解决方案17】:

        要获得一个介于 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 “向下舍入”范围。
        【解决方案18】:

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

        function genRandomNumber(how_many_number,min,max) {
        
                    // parameters
                    // how_many_number : 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) : maximun 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_number; 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;
                }
        

        【讨论】:

          【解决方案19】:

          我知道这个问题已经得到解答,但我的回答可能对某人有所帮助。

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

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

          希望这会对某人有所帮助。

          【讨论】:

          • Math.floor((Math.random() * 1) + 0);总是给 0
          • @madprops 因为最大数量是独占的。要获得 0 或 1,您应该将 2 设置为最大数。
          • 或者你只是在调用这个方法的函数中加+1
          【解决方案20】:

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

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

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

          【讨论】:

            【解决方案21】:

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

            const randomInteger = (min, max) => {
              const range = max - min;
              const maxGeneratedValue = 0xFFFFFFFF;
              const possibleResultValues = range + 1;
              const possibleGeneratedValues = maxGeneratedValue + 1;
              const remainder = possibleGeneratedValues % possibleResultValues;
              const maxUnbiased = maxGeneratedValue - remainder;
            
              if (!Number.isInteger(min) || !Number.isInteger(max) ||
                   max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) {
                throw new Error('Arguments must be safe integers.');
              } 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;
              } 
            
              let generated;
              do {
                generated = crypto.getRandomValues(new Uint32Array(1))[0];
              } while (generated > maxUnbiased);
            
              return min + (generated % possibleResultValues);
            };
            
            console.log(randomInteger(-8, 8));          // -2
            console.log(randomInteger(0, 0));           // 0
            console.log(randomInteger(0, 0xFFFFFFFF));  // 944450079
            console.log(randomInteger(-1, 0xFFFFFFFF));
            // Error: Range of 4294967296 covering -1 to 4294967295 is > 4294967295.
            console.log(new Array(12).fill().map(n => randomInteger(8, 12)));
            // [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]

            【讨论】:

              【解决方案22】:

              下面是一个 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 的值应该有适当的距离。
              【解决方案23】:
                  <!DOCTYPE html>
              <html>
                  <head>
                          <meta charset="utf-8" />
                  </head>
                  <body>
                      <script>
                          /*
              
                              assuming that window.crypto.getRandomValues is available
                              the real range would be fron 0 to 1,998 instead of 0 to 2,000
                              See javascript documentation for 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 创建一个包含最多 3 位数字的数组,最多为 999。这段代码很短。

              【讨论】:

                【解决方案24】:

                这是我对一个范围内的随机数的看法,因为我想获得一个从基数到指数范围内的随机数。例如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);
                

                【讨论】:

                  【解决方案25】:

                  想用一个例子来解释:

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

                  一般概述:

                  (i) 首先将其转换为范围 - 从 0 开始。

                  (ii) 然后将其转换为您想要的范围(这将是非常 容易完成)。

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

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

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

                  (5-5) - (25-5)

                  所以范围将是:

                  0-20 ...对吗?

                  b) 第二步:

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

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

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

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

                  c) 第三步

                  现在添加您在等式中减去的差(即 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 );
                  }
                  

                  【讨论】:

                    【解决方案26】:

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

                    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。事实上,我认为任何只有1个数字的最小值和最大值都是一样的;下界总是结果。
                    【解决方案27】:

                    Ionuț G. Stan 写了一个很好的答案,但它对我来说有点太复杂了。因此,我在 Jason Anello 的 https://teamtreehouse.com/community/mathfloor-mathrandom-max-min-1-min-explanation 找到了对相同概念的更简单解释。

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

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

                    【讨论】:

                      【解决方案28】:

                      我生成 0 到 n 之间随机数的方法,其中 n

                      Math.floor((Math.random() * 10) % n)
                      

                      【讨论】:

                      • 完美而简单的解决方案。
                      【解决方案29】:

                      /* 编写一个名为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(包括)之间的随机数 和最大(独家)。 */

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

                      /* 编写一个名为randFromTo 的函数,它接受两个数字 表示一个范围并返回 min(包括)之间的随机整数 和最大值(含) */

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

                      【讨论】:

                      • Beautiful,你能不能也注意到 randBetween 是(排他的)(排他的)?
                      【解决方案30】:

                      你可以把这段代码sn-p,

                      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
                      猜你喜欢
                      • 2022-06-30
                      • 2011-02-02
                      • 2016-05-04
                      • 2010-09-26
                      相关资源
                      最近更新 更多