Generate random number between two numbers in JavaScript

后端 未结 23 2049
走了就别回头了
走了就别回头了 2020-11-22 01:09

Is there a way to generate a random number in a specified range (e.g. from 1 to 6: 1, 2, 3, 4, 5, or 6) in JavaScript?

相关标签:
23条回答
  • 2020-11-22 01:26

    I discovered a great new way to do this using ES6 default parameters. It is very nifty since it allows either one argument or two arguments. Here it is:

    function random(n, b = 0) {
        return Math.random() * (b-n) + n;
    }
    
    0 讨论(0)
  • 2020-11-22 01:30
    function randomIntFromInterval(min, max) { // min and max included 
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    

    What it does "extra" is it allows random intervals that do not start with 1. So you can get a random number from 10 to 15 for example. Flexibility.

    0 讨论(0)
  • 2020-11-22 01:30

    Crypto-strong random integer number in range [a,b] (assumption: a < b )

    let rand= (a,b)=> a+(b-a+1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32|0
    
    console.log( rand(1,6) );

    0 讨论(0)
  • 2020-11-22 01:32

    Math.random() is fast and suitable for many purposes, but it's not appropriate if you need cryptographically-secure values (it's not secure), or if you need integers from a completely uniform unbiased distribution (the multiplication approach used in others answers produces certain values slightly more often than others).

    In such cases, we can use crypto.getRandomValues() to generate secure integers, and reject any generated values that we can't map uniformly into the target range. This will be slower, but it shouldn't be significant unless you're generating extremely large numbers of values.

    To clarify the biased distribution concern, consider the case where we want to generate a value between 1 and 5, but we have a random number generator that produces values between 1 and 16 (a 4-bit value). We want to have the same number of generated values mapping to each output value, but 16 does not evenly divide by 5: it leaves a remainder of 1. So we need to reject 1 of the possible generated values, and only continue when we get one of the 15 lesser values that can be uniformly mapped into our target range. Our behaviour could look like this pseudocode:

    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.
    

    The following code uses similar logic, but generates a 32-bit integer instead, because that's the largest common integer size that can be represented by JavaScript's standard number type. (This could be modified to use BigInts if you need a larger range.) Regardless of the chosen range, the fraction of generated values that are rejected will always be less than 0.5, so the expected number of rejections will always be less than 1.0 and usually close to 0.0; you don't need to worry about it looping forever.

    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]

    0 讨论(0)
  • 2020-11-22 01:34

    to return 1-6 like a dice basically,

    return Math.round(Math.random() * 5 + 1);
    
    0 讨论(0)
  • This works for me and produces values like Python's random.randint standard library function:

    
    function randint(min, max) {
       return Math.round((Math.random() * Math.abs(max - min)) + min);
    }
    
    console.log("Random integer: " + randint(-5, 5));
    
    0 讨论(0)
提交回复
热议问题