Skip to content

Instantly share code, notes, and snippets.

@bluesmoon
Last active February 15, 2022 12:43
Show Gist options
  • Save bluesmoon/7925696 to your computer and use it in GitHub Desktop.
Save bluesmoon/7925696 to your computer and use it in GitHub Desktop.
Pseudo-Random number generator that follows a Normal or Log-Normal distribution.

Marsaglia-polar.js

This script generates random numbers along a Normal or Log-normal distribution using the Marsaglia polar method.

There are four functions you can use:

  • normalRandom: Generate random numbers that follow a Normal distribution.
  • normalRandomInRange: Generate random numbers that follow a Normal distribution but are clipped to fit within a range
  • normalRandomScaled: Generate random numbers that follow a Normal distribution with a given mean and standard deviation
  • lnRandomScaled: Generate random numbers that follow a Log-normal distribution with a given geometric mean and geometric standard deviation

References:

var spareRandom = null;
function normalRandom()
{
var val, u, v, s, mul;
if(spareRandom !== null)
{
val = spareRandom;
spareRandom = null;
}
else
{
do
{
u = Math.random()*2-1;
v = Math.random()*2-1;
s = u*u+v*v;
} while(s === 0 || s >= 1);
mul = Math.sqrt(-2 * Math.log(s) / s);
val = u * mul;
spareRandom = v * mul;
}
return val;
}
function normalRandomInRange(min, max)
{
var val;
do
{
val = normalRandom();
} while(val < min || val > max);
return val;
}
function normalRandomScaled(mean, stddev)
{
var r = normalRandom();
r = r * stddev + mean;
return Math.round(r);
}
function lnRandomScaled(gmean, gstddev)
{
var r = normalRandom();
r = r * Math.log(gstddev) + Math.log(gmean);
return Math.round(Math.exp(r));
}
@bluesmoon
Copy link
Author

@chrislawes79 thanks for the report. I've updated the code the the version that works. I'd made some silly changes to scale the data and that was messing things up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment