JavaScript Math.random Normalverteilung (Gaußsche Glockenkurve)?

Lesezeit: 10 Minuten

Benutzer-Avatar
Mangooxx

Ich möchte wissen, ob die JavaScript-Funktion Math.random eine normale (vs. gleichmäßige) Verteilung verwendet oder nicht.

Wenn nicht, wie kann ich Zahlen erhalten, die eine Normalverteilung verwenden? Ich habe im Internet keine klare Antwort für einen Algorithmus gefunden, um zufällige normalverteilte Zahlen zu erstellen.

Ich möchte eine Schmidt-Maschine (deutscher Physiker) umbauen. Die Maschine erzeugt Zufallszahlen von 0 oder 1, und sie müssen normalverteilt sein, damit ich sie als Gaußsche Glockenkurve zeichnen kann.

Beispielsweise erzeugt die Zufallsfunktion 120 Zahlen (0 oder 1) und der Durchschnitt (Mittelwert) dieser summierten Werte muss nahe 60 liegen.

  • Keine Antwort (weil es nicht Ihre Frage war: P), aber das sollte helfen: meredithdodge.com/2012/05/30/…

    – Jongware

    30. August 2014 um 13:35 Uhr

  • Wenn Sie ein paar Math.random() mitteln, erhalten Sie bereits eine normale Verteilung mit sogar ein paar wenigen Aufrufen wie 3. siehe hier jsbin.com/tetizotugu/1/edit?js, Ausgabe Ändern Sie den ersten Parameter.

    – GameAlchemist

    18. Februar 2016 um 0:19 Uhr

  • Dies ist eine sehr häufige Verwirrung, da Statistik so gelehrt wird, als ob die Normalkurve das Wichtigste wäre, bevor die Menschen verstehen können, was sie ist. Wenn Sie 30 Durchschnitte (Summe xs / Länge xs) von 30 Münzen pro Probe nehmen würden. Diese 30 Mittelwerte wären ungefähr normalverteilt, und wenn Sie 30 weiter auf größere Zahlen erhöhen, konvergieren sie zu einer perfekten Normalkurve, die um 0,5 zentriert ist. random selbst ist eine uniforme int-Verteilung (mit den Parametern n, n + 1, normalerweise 0, 1), wie sie in c++ in der mersanne twister random engine mt19937 bekannt ist.

    – Dmitri

    11. August 2017 um 17:12 Uhr


  • Die Frage selbst ist wertvoll, da nach normalen dist-Zufallszahlen gefragt wird. Über den OP-Anwendungsfall konnte er es nicht so gut erklären wie Dmirty.

    – André Figueiredo

    18. Januar 2018 um 13:44 Uhr

Benutzer-Avatar
Maxwell Collard

Da dies meiner Erfahrung nach das erste Google-Ergebnis für “js gaussian random” ist, fühle ich mich verpflichtet, eine tatsächliche Antwort auf diese Anfrage zu geben.

Das Box-Muller-Transformation wandelt zwei unabhängige gleichförmige Zufallszahlen auf (0, 1) in zwei standardmäßige Gaußsche Zufallszahlen (Mittelwert 0, Varianz 1) um. Dies ist wahrscheinlich nicht sehr performant wegen der sqrt, logund cos Aufrufe, aber diese Methode ist den Ansätzen des zentralen Grenzwertsatzes (Summieren von N einheitlichen Variablen) überlegen, da sie die Ausgabe nicht auf den begrenzten Bereich (-N/2, N/2) beschränkt. Es ist auch ganz einfach:

// Standard Normalvariable mit Box-Muller-Transformation.  Funktion randn_bm () { var u = 0, v = 0;  while(u === 0) u = Math.random();  //Konvertieren [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 );
}

  • On 1000 samples, the range is [-3.10, 3.24] gist.github.com/Dorian/919f9ad749f28e5b57e655919d7eebb9

    – Dorian

    28. August 2016 um 0:35 Uhr


  • @Dorian Nicht ganz unerwartet, da die Wahrscheinlichkeit, dass eine normale Variable außerhalb dieses Bereichs liegt, etwa eins zu 1000 beträgt: $ python3; >>> import scipy.stats as stats; >>> 1 - ( stats.norm.cdf( 3.24 ) - stats.norm.cdf( -3.10 ) ); 0.0015652517111527375

    – Maxwell Collard

    29. August 2016 um 16:07 Uhr


  • @Dorian: Danke, am Ende habe ich eine ungefähre Gaußsche Funktion verwendet, die einen Bereich von hat [0, 1] wie in meinem Programm benötigt: stackoverflow.com/a/39187274/407213.

    – Dorian

    29. August 2016 um 17:04 Uhr

  • Warum nicht einfach einstellen u = 1 - Math.random() und die While-Schleife-Bedingung vergessen?

    – Vortico

    24. März 2020 um 12:54 Uhr

  • @Indra Ja, und das ist kein Problem. Tatsächlich können wir die While-Schleife für vergessen v und schreiben Sie die Funktion in einem etwas performanteren Einzeiler. return Math.sqrt(-2 * Math.log(1 - Math.random())) * Math.cos(2 * Math.PI * Math.random())

    – Vorticus

    18. Dezember 2020 um 12:45 Uhr

Benutzer-Avatar
joshuakcockrell

Normalverteilung zwischen 0 und 1

Aufbauend auf Maxwells Antwort verwendet dieser Code die Box-Muller-Transformation um Ihnen eine Normalverteilung zwischen 0 und 1 einschließlich zu geben. Es werden die Werte nur neu abgetastet, wenn sie mehr als 3,6 Standardabweichungen entfernt sind (weniger als 0,02 % Wahrscheinlichkeit).

Funktion randn_bm () { let u = 0, v = 0;  while(u === 0) u = Math.random();  //Konvertieren [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/

  • What exactly the skew factor represents? It doesn’t seems to represent standard deviation or variance. How can I understand it mathematically?

    – user5834627

    Dec 16, 2019 at 17:41

  • @André I admit, there’s not much mathematical backing behind the skew factor in my answer here. It was just a convenient way of stretching or shrinking the data for my use case. If you want to implement a legit skew-normal transform with proper mean, standard deviation, and shape variables, you could check out this link. spin.atomicobject.com/2019/09/30/skew-normal-prng-javascript

    – joshuakcockrell

    Dec 17, 2019 at 1:26

  • Also, here is my original JS Fiddle for this answer jsfiddle.net/ktq9jaoe/4 Maybe I will modify it to include more mathematical mean/std dev/shape variables.

    – joshuakcockrell

    Dec 17, 2019 at 1:26

  • Great answer, however I found a small bug in your code: ` if (num > 1 || num < 0) num = randn_bm(min, max, skew); // resample between 0 and 1 if out of range ` …should be: ` if (num > 1 || num < 0) { num = randn_bm(min, max, skew); // resample between 0 and 1 if out of range } else { … } return num; ` That is, only scale the final number if not re-sampling.

    – MushyMiddle

    Jan 15, 2020 at 19:45


  • Why can’t I make it work when min is 0 and max is 1? I want to mimic native random method which outputs only between 0 and 1

    – vsync

    Mar 7, 2021 at 13:05

user avatar
kodvin

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.

  • Just a heads up in case you are wondering where the upvotes are coming from. This answer was mentioned in a reddit thread, which triggered the meta effect . reddit.com/r/ProgrammerHumor/comments/a3ngy7/…

    – LukeG

    Dec 6, 2018 at 20:08

  • …And I posted that comment on Reddit. Now this answer has positive votes and I am proud of what I did.

    – SCLeo

    Dec 6, 2018 at 23:41

  • Wow, that made my date, because this question was really old and i could not remove it. Shame stack gives max of 200 per day, so i would have got a 1000+ points .But still it feels amazing :D, thanks reddit for support(Also SCLeo) . 🙂

    – kodvin

    Dec 7, 2018 at 6:58

  • All these answers, except a few ones, do not realize the random distribution do not distribute between 0 and 1, but can attain any arbitrarily high value in some cases. Thar is an outrageous confusion.

    – Brethlosze

    Apr 25, 2021 at 6:34


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

user avatar
Jóhann Þórir Jóhannsson

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

  • This is the Marsaglia polar method.

    – Rafi

    Mar 28, 2016 at 6:56

  • Can you explain the reasoning behind the last 3 lines of the returned function? Why does retval have to be positive? What if the mean was, e.g., 0? Then I would expect both positive and negative samples.

    – Chris K

    Dec 16, 2016 at 13:49

  • @ChrisK. Until reversed in sign, retvar will be the distributed around the negative of the supplied mean. If you pass 0 for the mean, it won’t matter if you reverse the sign or not. In both cases, you will have an equal positive and negative distribution.

    – John Pankowicz

    Oct 22, 2019 at 1:04

  • @ChrisK. You are right: due to the last 3 lines of code the value returned by gaussian function is always positive and so it cannot be a random value from a gaussian distribution.

    – Alessandro Jacopson

    Mar 1, 2020 at 11:54

  • I think Knuth does not have if(retval > 0) return retval; return -retval;

    – Alessandro Jacopson

    Mar 1, 2020 at 11:55

user avatar
Joe

Function that utilises the central limit theorem.

function normal(mu, sigma, nsamples){
    if(!nsamples) nsamples = 6
    if(!sigma) sigma = 1
    if(!mu) mu=0

    var run_total = 0
    for(var i=0 ; i<nsamples ; i++){
       run_total += Math.random()
    }

    return sigma*(run_total - nsamples/2)/(nsamples/2) + mu
}

  • This is the Marsaglia polar method.

    – Rafi

    Mar 28, 2016 at 6:56

  • Can you explain the reasoning behind the last 3 lines of the returned function? Why does retval have to be positive? What if the mean was, e.g., 0? Then I would expect both positive and negative samples.

    – Chris K

    Dec 16, 2016 at 13:49

  • @ChrisK. Until reversed in sign, retvar will be the distributed around the negative of the supplied mean. If you pass 0 for the mean, it won’t matter if you reverse the sign or not. In both cases, you will have an equal positive and negative distribution.

    – John Pankowicz

    Oct 22, 2019 at 1:04

  • @ChrisK. You are right: due to the last 3 lines of code the value returned by gaussian function is always positive and so it cannot be a random value from a gaussian distribution.

    – Alessandro Jacopson

    Mar 1, 2020 at 11:54

  • I think Knuth does not have if(retval > 0) return retval; return -retval;

    – Alessandro Jacopson

    Mar 1, 2020 at 11:55

user avatar
Andre Figueiredo

From the spec:

15.8.2.14 random ( )

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, it’s a uniform distribution, not normal or Gaussian. That’s what you’re going to find in just about any standard random number facility in any basic language runtime outside of specialized statistics libraries.

1158060cookie-checkJavaScript Math.random Normalverteilung (Gaußsche Glockenkurve)?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy