Can I have multiple independent random number generators with different seeds?


I’m hoping to use multiple random number generators so that I can have different random processes that don’t interfere with each other and can be seeded for some amount of consistency. Is this possible with p5.js?



Normally, we would expect that each instance of p5 would have its own random seed. :seedling:

In such case, we could instantiate a new p5 and call its noCanvas(), just for the sake of using its random() method w/ a specific randomSeed(). :money_mouth_face:

However, the code responsible to generate seeded pseudo-random values in p5js is a singleton object stored in a closure variable named lcg: :neutral_face:

B/c lcg is a closure variable, no matter how many times we instantiate the class p5, there’ll only be 1 unique lcg object shared across all p5 instances! :astonished:

Instead, lcg needs to be changed into a class property, so each instance of that class would have its own lcg, rather than a shared 1. :face_with_monocle:

BtW, the p5js library is littered w/ such closure local variables, which are a dumb, poor, short-sighted attempt to make private, unaccessible states. :male_detective:

And considering the library is supposed to have multiple instances of it at the same time, it shouldn’t have any shared states at all! :no_good_man:

Now, as a workaround, you can simply rewrite the “random.js” file as a class, whose instances will have their own seed state. :bulb:

More discussion about pseudo-random generation: :sunglasses:



Thanks for the incredibly thorough and informative answer, @GoToLoop. If I am running p5 inside of another js environment and have access to math.random, does that change the answer? I’m working with a friend on a web app that uses javascript, p5, react, and probably some other things I’m not aware of. I’m a js noob.



The only sensible solution is creating a class for random + seed. :seedling:

If you prefer not to, the only other feasible solution is using iframes: :framed_picture:

Let’s say you need 10 unique seeds. Then you’re gonna need 10 iframes w/ a p5js in it. :grimacing:

1 Like


Gotcha. Thank you so much! This has been extremely helpful.



If you just want a standalone random class that takes a seed, I implemented one recently as part of a cross-language processing randomness kit called CommonRandom. (The goal was repeatable psuedorandom generators across JavaScript, Java, and python mode sketches). The pseudo-random method is based on XORshift. Create as many RandAnywhere objects as you like an use them individually.

Here is a demo sketch:

var rand;

function setup() {
  createCanvas(400, 200);
  //rand = new RandAnywhere(0);
  //// rand = new RandAnywhere(1536694537142); // example of a specific millisecond timecode

  // print a series of examples values from a specific seed
  // corresponding to epoch milliseconds, as if a seed was
  // requested on 2018-11-11 at 11:11:11.
  rand = new RandAnywhere(1541963471000);
  print(rand.nextLong());        // 1043807117
  print(rand.nextInt());         // 935077768
  print(rand.random());          // 0.7892195325294601
  print(rand.random(10));        // 1.1313271294959482
  print(rand.random(0, width));  // 140.0591152441032
  // reset seed

  // set native seed

 * draw a series of random lines
function draw() {
  if (frameCount>64) {
  stroke(0, 0, 0);
  line(rand.random(0, width/2), rand.random(0, height), 
    rand.random(0, width/2), rand.random(0, height));
  stroke(255, 0, 0);
  translate(width/2, 0);
  line(random(0, width/2), random(0, height), 
    random(0, width/2), random(0, height));

 * a simple cross-language pseudorandom number generator (PRNG)
 * implemented in Processing (Java)
 * inspired by
function RandAnywhere(newSeed) {
  // a simple XorShift implementation
  // inspired by
  this.a = 1664525;
  this.c = 1013904223;
  this.Integer_MAX_VALUE = 2147483647;
  // Defaults to current system time in milliseconds.
  if (newSeed === undefined) {
    var d = new Date();
    newSeed = d.getMilliseconds()%this.Integer_MAX_VALUE;

 * Updates seed based on past value, returns new value.
 * Returns unsigned 32bit value stored in a long.
 * (named for cross-language compatability with Java nextLong)
RandAnywhere.prototype.nextLong = function() {
  // The intermediate result fits in 52 bits, so no overflow
  this.seed = ((this.seed * 1664525 + 1013904223) | 0) >>> 0;
  return this.seed;
 * Returns next long wrapped to the max (Java) integer value.
 * (for cross-language compatability)
 * Implemented so that calls to nextInt or nextLong stay in sync,
 * the next seed internally is always updated to the next long.
RandAnywhere.prototype.nextInt = function() {
  var next = this.nextLong();
  return next%this.Integer_MAX_VALUE;
 * Set the current seed.
RandAnywhere.prototype.randomSeed = function(newSeed) {
  this.seed = newSeed%this.Integer_MAX_VALUE;
 * Return a random float in the specified range.
 * 0 arguments: 0-1
 * 1 argument:  0-max
 * 2 arguments: min-max
RandAnywhere.prototype.random = function(a, b) {
  if(!a && !b){
    rmin = 0;
    rmax = 1;
  } else if(!b){
    rmin = 0;
    rmax = a;
  } else {
    rmin = a;
    rmax = b;
  return map(this.nextInt(), 0, this.Integer_MAX_VALUE, rmin, rmax);


Thanks, @jeremydouglass! I’ll take a stab at plugging that into my code.