Seedable JavaScript random number generator

前端 未结 9 710
暖寄归人
暖寄归人 2020-11-22 10:13

The JavaScript Math.random() function returns a random value between 0 and 1, automatically seeded based on the current time (similar to Java I believe). However, I don\'t

9条回答
  •  灰色年华
    2020-11-22 10:37

    If you don't need the seeding capability just use Math.random() and build helper functions around it (eg. randRange(start, end)).

    I'm not sure what RNG you're using, but it's best to know and document it so you're aware of its characteristics and limitations.

    Like Starkii said, Mersenne Twister is a good PRNG, but it isn't easy to implement. If you want to do it yourself try implementing a LCG - it's very easy, has decent randomness qualities (not as good as Mersenne Twister), and you can use some of the popular constants.

    EDIT: consider the great options at this answer for short seedable RNG implementations, including an LCG option.

    function RNG(seed) {
      // LCG using GCC's constants
      this.m = 0x80000000; // 2**31;
      this.a = 1103515245;
      this.c = 12345;
    
      this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
    }
    RNG.prototype.nextInt = function() {
      this.state = (this.a * this.state + this.c) % this.m;
      return this.state;
    }
    RNG.prototype.nextFloat = function() {
      // returns in range [0,1]
      return this.nextInt() / (this.m - 1);
    }
    RNG.prototype.nextRange = function(start, end) {
      // returns in range [start, end): including start, excluding end
      // can't modulu nextInt because of weak randomness in lower bits
      var rangeSize = end - start;
      var randomUnder1 = this.nextInt() / this.m;
      return start + Math.floor(randomUnder1 * rangeSize);
    }
    RNG.prototype.choice = function(array) {
      return array[this.nextRange(0, array.length)];
    }
    
    var rng = new RNG(20);
    for (var i = 0; i < 10; i++)
      console.log(rng.nextRange(10, 50));
    
    var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    for (var i = 0; i < 10; i++)
      console.log(rng.choice(digits));

提交回复
热议问题