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));
}
@chrislawes79
Copy link

Hi. I tested the normalRandomScaled() function and found it doesn't return a normal distribution with the specified standard deviation. I created sample sizes of 59 with a mean of 1752 and sd of 85 and returned distributions had sd's of around 6.

Kind regards,

Chris

@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