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

**URL:** <https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125>\
**Category:** Coding Questions\
**Created:** [April 9, 2019, 11:54am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125 "2019-04-09T11:54:03Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 9, 2019, 11:54am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/1 "2019-04-09T11:54:03Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [April 9, 2019, 6:10pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/2 "2019-04-09T18:10:26Z")

</div>

> [@neel](#):
>
> Is this possible with p5.js?

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

In such case, we could instantiate a `new` p5 and call its [**noCanvas()**](http://p5js.org/reference/#/p5/noCanvas), just for the sake of using its [**random()**](http://p5js.org/reference/#/p5/random) method w/ a specific [**randomSeed()**](http://p5js.org/reference/#/p5/randomSeed). 🤑

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

> <https://github.com/processing/p5.js/blob/0.8.0/src/math/random.js#L16-L46>

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! 😲

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. 🧐

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

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! 🙅‍♂️

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

More discussion about pseudo-random generation: 🕶

> [@How would I apply randomSeed( )](https://discourse.processing.org/t/how-would-i-apply-randomseed/10054):
>
> Page 221 - 223 - Example 8-9: Move Shapes Randomly At the end of the example, there’s a NOTE about randomSeed( ). I checked out the Reference at [https://p5js.org/reference/#/p5/randomSeed](https://p5js.org/reference/#/p5/randomSeed) I’m trying to figure out how to apply randomSeed( ) to Example 8-9: Move Shapes Randomly? I added randomSeed( ) to example (including the example with constrain( )) and can’t get to work in a way that seems appropriate. Code example without constrain( ): var speed = 2.5; var diameter = 20; var x; var y; fu…

---

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 10, 2019, 12:34am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/3 "2019-04-10T00:34:08Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [April 10, 2019, 12:45am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/4 "2019-04-10T00:45:54Z")

</div>

> [@neel](#):
>
> If I am running p5 inside of another js environment…

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

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

> [@Switch Between Multiple p5.js Sketches in Single Webpage](https://discourse.processing.org/t/switch-between-multiple-p5-js-sketches-in-single-webpage/9981/4):
>
> Assuming you have a variable iframe which points to the HTMLIFrameElement of the running sketch you wanna pause, you can call: iframe.contentWindow.noLoop(); Alternatively, the window property of each HTMLIFrameElement is stored in the frames[] pseudo-array: Let’s say you wanna pause the sketch running at the 3rd created HTMLIFrameElement, you simply call: frames[2].noLoop();

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

---

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 10, 2019, 12:57am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/5 "2019-04-10T00:57:34Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 12, 2019, 4:29pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/6 "2019-04-12T16:29:21Z")

</div>

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:

```auto
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
  rand.randomSeed(0);

  // set native seed
  randomSeed(0);
}

/**
 * draw a series of random lines
 */
function draw() {
  if (frameCount>64) {
    noLoop();
  }
  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 https://stackoverflow.com/a/34659107/7207622
 */
function RandAnywhere(newSeed) {
  // a simple XorShift implementation
  // inspired by https://stackoverflow.com/a/34659107/7207622
  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;
  }
  this.randomSeed(newSeed);
}

/**
 * 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);
}

```

---

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 14, 2019, 8:08pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/7 "2019-04-14T20:08:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 24, 2019, 1:13am UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/8 "2019-04-24T01:13:08Z")

</div>

@jeremydouglass Do you find that the first number generated by this is always small? I keep seeding it with random and rerunning the code, and the first result between 0 and 5 is always .47.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 24, 2019, 3:49pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/9 "2019-04-24T15:49:37Z")

</div>

> [@neel](#):
>
> I keep seeding it with random and rerunning the code, and the first result between 0 and 5 is always .47.

Do you mean that the first five values you get back are the same? I’m not seeing that.

```auto
RandAnywhere rand;

void setup() {
  rand = new RandAnywhere(1);
  println(rand.random()); // 0.47291106
  println(rand.random()); // 0.73854136
  
  // reset seed
  rand.randomSeed(1000);
  println(rand.random()); // 0.24724080
  println(rand.random()); // 0.96466416
}

```

I think a property of XorShift (which I am not an expert in) is that the seed and the first value are correlated. So you can’t walk through seeds 0, 1, 2, 3 (or seeds 1000, 1001, 1002, 1003) and take the first value and expect the results to be pseudorandom. That is not the correct way to use it – choose one seed (or don’t) and then walk through the results for psuedorandomness. If you want dramatically initial values from different seeds, separate them by e.g. 100 or 1000 – but still don’t walk through seeds this way.

```auto
RandAnywhere rand;

void setup() {
  rand = new RandAnywhere();
  println("\nwrong way");
  for(int i=0; i<5; i++){
    rand.randomSeed(i);
    println(rand.random());
  }
  println("\nstill wrong");
  for(int i=1000; i<1005; i++){
    rand.randomSeed(i);
    println(rand.random());
  }
  println("\nright way");
  rand = new RandAnywhere();
  for(int i=0; i<5; i++){
    println(rand.random());
  }
}

```

> wrong way  
> 0.47213593  
> 0.47291106  
> 0.47368616  
> 0.47446126  
> 0.47523636
> 
> still wrong  
> 0.2472408  
> 0.24801591  
> 0.24879101  
> 0.24956611  
> 0.2503412
> 
> right way  
> 0.33733737  
> 0.9579861  
> 0.28542346  
> 0.9715376  
> 0.09700281

---

<div class="post-metadata">

**Author:** ![neel](https://avatars.discourse-cdn.com/v4/letter/n/f475e1/32.png) [@neel](https://discourse.processing.org/u/neel)\
**Post date:** [April 24, 2019, 9:30pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/10 "2019-04-24T21:30:56Z")

</div>

Thanks for the response, @jeremydouglass. That’s not quite what I meant, and I realized I was including unnecessary and confusing details instead of just posting code.

I’ve been using random() as the seed for my new generators, and the first number they generate always tends to be similar. I’ve been attempting to use random() as the seed so that I use randomSeed() for processing’s built-in random function and get consistent results from each of the RandAnywhere generators that I create.

This code generates very consistent first random values that are approximately 2.36, but the second random value always seems to have a larger distribution.

```auto
function setup() {
  noLoop();
}

function draw() {
  for (let i = 0; i < 100; i++) {
   let a = new RandAnywhere(random());
    console.log("first random " + a.random(0,5));
    console.log("second random " + a.random(0,5));
    
  }
}

function RandAnywhere(newSeed) {
  // a simple XorShift implementation
  // inspired by https://stackoverflow.com/a/34659107/7207622
  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;
  }
  this.randomSeed(newSeed);
}

/**
 * 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);
}

```

The first and second values are shown here…

```auto
first random 2.362770860717991 
second random 3.525784948619914 
first random 2.363426078745828 
second random 4.152572226781665 
first random 2.361602986865492 
second random 4.570561526143254 
first random 2.3624849167477735 
second random 2.564898146113799 
first random 2.3632667993024303 
second random 4.027956830816323 
first random 2.3640642186459453 
second random 1.352388975840243 
first random 2.3611599264485577 
second random 2.0854213680538445 
first random 2.361820350569589 
second random 1.3778809161753771 
first random 2.3611923131911046 
second random 0.9939639833727685 
first random 2.3614427574730676 
second random 2.8647322221029237 
first random 2.3619068401688277 
second random 0.3419810232436196 
first random 2.3606833407472276 
second random 3.7966072344205375 
first random 2.361152182501346 
second random 4.195427645088838 
first random 2.362037302163447 
second random 2.4992325145282 
first random 2.3645188041797462 
second random 3.0213742717268754 
first random 2.3635844315232637 
second random 2.734728966716085 
first random 2.3631429171018037 
second random 2.8229369259546218 
first random 2.363937826530979 
second random 0.9695539092503274 
first random 2.3624895454209716 
second random 0.2694403963486852 
first random 2.3635319817641434 
second random 0.4307937041999743 
first random 2.3642933263277137 
second random 2.7078527946527364 
first random 2.3620608390132247 
second random 1.6769073725104833 
first random 2.363296459598139 
second random 3.3982605223535844 
first random 2.3643980349248266 
second random 1.9979303199788232 
first random 2.364150826988812 
second random 0.5141408161791697 
first random 2.3629668040028617 
second random 4.678281049559955 
first random 2.362915171479301 
second random 3.734654806896418 
first random 2.3638024960475987 
second random 0.7085811629465694 
first random 2.364173458127386 
second random 3.18423673658829 
first random 2.363136667927325 
second random 2.421029781653094 

```

It looks like the issue is reduced if I use random(1000000) as the seed.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 25, 2019, 8:44pm UTC](https://discourse.processing.org/t/can-i-have-multiple-independent-random-number-generators-with-different-seeds/10125/11 "2019-04-25T20:44:49Z")

</div>

> [@neel](#):
>
> This code generates very consistent first random values that are approximately 2.36, but the second random value always seems to have a larger distribution.

I think you might be misunderstanding. The point of a stable PNRG with a seed is for the values to be **identical** , not very close. The “very close” values are more like a bug – in this case, caused by using that PNRG in the wrong way. There is also a limitation in the code – it generates a default seed from Date milliseconds, so if you create a batch of randomseeds very close together their first values will be correlated.

So, coming back to your original question:

> [@neel](#):
>
> I can have different random processes that don’t interfere with each other and can be seeded for some amount of consistency

```auto
var rand1;
var rand2;
var rand3;
function setup() {
  createCanvas(400, 200);
  rand1 = new RandAnywhere(0);
  rand2 = new RandAnywhere(1000);
  rand3 = new RandAnywhere(2000);
}

```

Then use `rand1.random()` as one generator, `rand2.random()` as another, etc. – no more setting seeds, just call each with no arguments to get the next random number.
