JavaScript Math.random Normal distribution (Gaussian bell curve)?

Since this is the first Google result for "js gaussian random" in my experience, I feel an obligation to give an actual answer to that query.

The Box-Muller transform converts two independent uniform variates on (0, 1) into two standard Gaussian variates (mean 0, variance 1). This probably isn't very performant because of the sqrt, log, and cos calls, but this method is superior to the central limit theorem approaches (summing N uniform variates) because it doesn't restrict the output to the bounded range (-N/2, N/2). It's also really simple:

// Standard Normal variate using Box-Muller transform.
function randn_bm() {
    var u = 0, v = 0;
    while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
    while(v === 0) v = Math.random();
    return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}

Normal Distribution Between 0 and 1

Building on Maxwell's Answer, this code uses the Box–Muller transform to give you a normal distribution between 0 and 1 inclusive. It just resamples the values if it's more than 3.6 standard deviations away (less than 0.02% chance).

function randn_bm() {
  let u = 0, v = 0;
  while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
  while(v === 0) v = Math.random();
  let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
  num = num / 10.0 + 0.5; // Translate to 0 -> 1
  if (num > 1 || num < 0) return randn_bm() // resample between 0 and 1
  return num
}

Visualizations

enter image description here

n = 100

enter image description here

n = 10,000

enter image description here

n = 10,000,000

Normal Distribution With Min, Max, Skew

This version allows you to give a min, max, and skew factor. See my usage examples at the bottom.

function randn_bm(min, max, skew) {
  let u = 0, v = 0;
  while(u === 0) u = Math.random() //Converting [0,1) to (0,1)
  while(v === 0) v = Math.random()
  let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )
  
  num = num / 10.0 + 0.5 // Translate to 0 -> 1
  if (num > 1 || num < 0) 
    num = randn_bm(min, max, skew) // resample between 0 and 1 if out of range
  
  else{
    num = Math.pow(num, skew) // Skew
    num *= max - min // Stretch to fill range
    num += min // offset to min
  }
  return num
}

enter image description here

randn_bm(-500, 1000, 1);

enter image description here

randn_bm(10, 20, 0.25);

enter image description here

randn_bm(10, 20, 3);

Here is the JSFiddle for these screenshots: https://jsfiddle.net/2uc346hp/


I want to know if the JavaScript function Math.random is normal distribution or not

Javascript Math.random is not a Normal Distribution(Gaussian bell curve). From ES 2015, 20.2.2.27 "Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments." So the provided collection when n is high enough we will get approximately uniform distribution. All values in the interval will have equal probability of appearance(straight line parallel to the x axis, denoting number between 0.0 and 1.0).

how can I get numbers which are normal distribution

There are several ways of getting collection of numbers with a normal distribution. As answered by Maxwell Collard the Box-Muller transform does transform uniform distribution to normal distribution(the code can be found in Maxwell Collard answer).

An answer to another stackoverflow answer to a question has a reply with other uniform distribution to normal distribution algorithms. Such as: Ziggurat, Ratio-of-uniforms, Inverting the CDF Besides one of the answers says that: says:

The Ziggurat algorithm is pretty efficient for this, although the Box-Muller transform is easier to implement from scratch (and not crazy slow).

And finally

I want to rebuilt a Schmidt-machine (German physicist), the machine produces random numbers of 0 or 1 and they have to be normal distributed so I can draw them in Gaussian bell curve.

When we have only two values (0 or 1) Gaussian curve looks the same as uniform distribution with 2 possible values. That is why a simple

function randomZero_One(){
    return Math.round(Math.random());
}

would suffice. It would return pseudo-randomly with approximately equal probability values 0 and 1.


I wanted to have approximately gaussian random numbers between 0 and 1, and after many tests I found this to be the best:

function gaussianRand() {
  var rand = 0;

  for (var i = 0; i < 6; i += 1) {
    rand += Math.random();
  }

  return rand / 6;
}

And as a bonus:

function gaussianRandom(start, end) {
  return Math.floor(start + gaussianRand() * (end - start + 1));
}

The Javascript Math.random() pseudorandom function returns variates that are equally distributed between 0 and 1. To get a Gaussian distribution I use this:

// returns a gaussian random function with the given mean and stdev.
function gaussian(mean, stdev) {
  var y2;
  var use_last = false;
  return function() {
    var y1;
    if (use_last) {
      y1 = y2;
      use_last = false;
    } else {
      var x1, x2, w;
      do {
        x1 = 2.0 * Math.random() - 1.0;
        x2 = 2.0 * Math.random() - 1.0;
        w = x1 * x1 + x2 * x2;
      } while (w >= 1.0);
      w = Math.sqrt((-2.0 * Math.log(w)) / w);
      y1 = x1 * w;
      y2 = x2 * w;
      use_last = true;
    }

    var retval = mean + stdev * y1;
    if (retval > 0)
      return retval;
    return -retval;
  }
}

// make a standard gaussian variable.     
var standard = gaussian(100, 15);

// make a bunch of standard variates
for (i = 0; i < 1000; i++) {
  console.log( standard() )
}

I think I got this from Knuth.

Plot can be seen here