Wednesday, February 23, 2011

Javascript random numbers with custom seed - part 2

Generator created in previous example was able only to create integer numbers from zero to the given maximum (2^50) using provided seed. But in most cases we need random numbers from some range, so lets modify previous example and add 'min' and 'max' arguments to the .next() method. Also, to make it more like the native Math.rand(), let's make it generating floats from 0 to 1.
var CustomRandom = function(nseed) {    
  
  var seed,    
    constant = Math.pow(2, 13)+1,    
    prime = 1987,    
//any prime number, needed for calculations, 1987 is my favorite:)  
    maximum = 1000;    
//maximum number needed for calculation the float precision of the numbers (10^n where n is number of digits after dot)  
    if (nseed) {    
      seed = nseed;    
    }    
    
    if (seed == null) {    
//before you will correct me in this comparison, read Andrea Giammarchi's text about coercion http://goo.gl/N4jCB  
      
      seed = (new Date()).getTime();   
//if there is no seed, use timestamp     
    }     
    
    return {    
      next : function(min, max) {    
        seed *= constant;    
        seed += prime;    
           
      
        return min && max ? min+seed%maximum/maximum*(max-min) : seed%maximum/maximum;  
// if 'min' and 'max' are not provided, return random number between 0 & 1  
      }    
    }    
}  
Now its easy to use it in such a way:
var rng = CustomRandom(23);
//use '23' as a seed
    rng.next(); // 0.426
    rng.next(); // 0.205
In the next part I will show some GameDev related examples of using Random Number Generators with custom seeds.

Check 1st part of the "Javascript random numbers with custom seed" tutorial

7 comments:

  1. This rng is badly broken, it tends to repeat after 8 numbers or so.

    ReplyDelete
  2. CustomRandom(1).next() generates only pair decimal numbers after the few first (eg 0.808, 0.996) and NaN after about 90 numbers

    ReplyDelete
  3. Yes, great script, thank a lot!
    An error on step 78 (not 90!) is releted with seed value goes to Infinity. That can be fixed like this:


    next : function(i) {

    // aded line:
    while (seed > constant) seed = seed/prime;

    seed *= constant;
    seed += prime;

    return min && max ? min+seed%maximum/maximum*(max-min) : seed%maximum/maximum;
    }

    ReplyDelete
  4. Awesome RNG, though I did notice that if your min or max is a 0 or a negative, the return statements won't work as they are right now.

    if(min != undefined && max != undefined) {
    return Math.floor(min+seed%maximum/maximum*(max-min))
    } else {
    return seed%maximum/maximum;
    }

    That fixed it for me. (The change to Math.floor was just because I wanted whole numbers if I gave it a min and a max)

    ReplyDelete