Seeding the random number generator in Javascript

后端 未结 13 1399
野趣味
野趣味 2020-11-22 09:28

Is it possible to seed the random number generator (Math.random) in Javascript?

相关标签:
13条回答
  • 2020-11-22 10:17

    No, but here's a simple pseudorandom generator, an implementation of Multiply-with-carry I adapted from Wikipedia (has been removed since):

    var m_w = 123456789;
    var m_z = 987654321;
    var mask = 0xffffffff;
    
    // Takes any integer
    function seed(i) {
        m_w = (123456789 + i) & mask;
        m_z = (987654321 - i) & mask;
    }
    
    // Returns number between 0 (inclusive) and 1.0 (exclusive),
    // just like Math.random().
    function random()
    {
        m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
        m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
        var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
        result /= 4294967296;
        return result;
    }
    

    EDIT: fixed seed function by making it reset m_z
    EDIT2: Serious implementation flaws have been fixed

    0 讨论(0)
  • 2020-11-22 10:20

    No, it is not, but it's fairly easy to write your own generator, or better yet use an existing one. Check out: this related question.

    Also, see David Bau's blog for more information on seeding.

    0 讨论(0)
  • 2020-11-22 10:22

    Combining some of the previous answers, this is the seedable random function you are looking for:

    Math.seed = function(s) {
        var mask = 0xffffffff;
        var m_w  = (123456789 + s) & mask;
        var m_z  = (987654321 - s) & mask;
    
        return function() {
          m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
          m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;
    
          var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
          result /= 4294967296;
          return result;
        }
    }
    
    var myRandomFunction = Math.seed(1234);
    var randomNumber = myRandomFunction();
    
    0 讨论(0)
  • 2020-11-22 10:22

    Math.random no, but the ran library solves this. It has almost all distributions you can imagine and supports seeded random number generation. Example:

    ran.core.seed(0)
    myDist = new ran.Dist.Uniform(0, 1)
    samples = myDist.sample(1000)
    
    0 讨论(0)
  • 2020-11-22 10:25

    I have written a function that returns a seeded random number, it uses Math.sin to have a long random number and uses the seed to pick numbers from that.

    Use :

    seedRandom("k9]:2@", 15)
    

    it will return your seeded number the first parameter is any string value ; your seed. the second parameter is how many digits will return.

         function seedRandom(inputSeed, lengthOfNumber){
    
               var output = "";
               var seed = inputSeed.toString();
               var newSeed = 0;
               var characterArray = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','y','x','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','U','R','S','T','U','V','W','X','Y','Z','!','@','#','$','%','^','&','*','(',')',' ','[','{',']','}','|',';',':',"'",',','<','.','>','/','?','`','~','-','_','=','+'];
               var longNum = "";
               var counter = 0;
               var accumulator = 0;
    
               for(var i = 0; i < seed.length; i++){
                    var a = seed.length - (i+1);
                    for(var x = 0; x < characterArray.length; x++){
                         var tempX = x.toString();
                         var lastDigit = tempX.charAt(tempX.length-1);
                         var xOutput = parseInt(lastDigit);
                         addToSeed(characterArray[x], xOutput, a, i); 
                    }                  
               }
    
                    function addToSeed(character, value, a, i){
                         if(seed.charAt(i) === character){newSeed = newSeed + value * Math.pow(10, a)}
                    }
                    newSeed = newSeed.toString();
    
                    var copy = newSeed;
               for(var i=0; i<lengthOfNumber*9; i++){
                    newSeed = newSeed + copy;
                    var x = Math.sin(20982+(i)) * 10000;
                    var y = Math.floor((x - Math.floor(x))*10);
                    longNum = longNum + y.toString()
               }
    
               for(var i=0; i<lengthOfNumber; i++){
                    output = output + longNum.charAt(accumulator);
                    counter++;
                    accumulator = accumulator + parseInt(newSeed.charAt(counter));
               }
               return(output)
          }
    
    0 讨论(0)
  • 2020-11-22 10:30

    To write your own pseudo random generator is quite simple.

    The suggestion of Dave Scotese is useful but, as pointed out by others, it is not quite uniformly distributed.

    However, it is not because of the integer arguments of sin. It's simply because of the range of sin, which happens to be a one dimensional projection of a circle. If you would take the angle of the circle instead it would be uniform.

    So instead of sin(x) use arg(exp(i * x)) / (2 * PI).

    If you don't like the linear order, mix it a bit up with xor. The actual factor doesn't matter that much either.

    To generate n pseudo random numbers one could use the code:

    function psora(k, n) {
      var r = Math.PI * (k ^ n)
      return r - Math.floor(r)
    }
    n = 42; for(k = 0; k < n; k++) console.log(psora(k, n))
    

    Please also note that you cannot use pseudo random sequences when real entropy is needed.

    0 讨论(0)
提交回复
热议问题