Generating Normal (Gaussian) Distributed Random Numbers

Abstract

Random numbers are an essential part of computer games and simulations. Functions in most software development tools output random numbers with uniform distribution. Simulations often need random numbers in normal distribution. An easy way to approximate normal distribution is to add three random numbers:

G = X + X + X

X = a uniformly distributed random number between -1 and 1.

G ~ a standard normal random number.

To adjust the result for your needs, just multiply by your desired standard deviation and add your desired mean.

R = Gσ + μ

Try it now: Mean = 100, Standard Deviation = 10

Did You Get All That?

If not, here is a little more info with definitions, explanations and examples.

What Are Normally Distributed Random Numbers and Why Do I Need Them?

Faye Valentine Let's say you are creating an adventure in the land of the vampiric gun-slinging samurai space pirate ninja schoolgirls. You have decided that the female inhabitants should have an average chest measurement of 36 inches. (Why not? It's your world!) You would not want all of the anime babes to have identical measurements though. Variety is the spice of simulated life. You could have a pseudo random number generator give you a number from 34 to 38. The number would be uniformly distributed, meaning there is an equal chance of getting 34, 35, 36, 37, and 38. Not only is that boring and predictable, but you would deny the possibility of a lithe 32 or a buxom 40! What kind of cold, harsh creator are you? Shame!

I hope you agree that it'd be nice to allow an occasional outlying figure, but make it more the exception than the rule. That is usually how the real world works and I have always been a fan of reality. In short, we need a system that has differing probabilities with the most common outcome in the middle and becoming less probable as the values get farther away from the average. The most common way to represent this statistically is called normal distribution or Gaussian distribution. (It is also sometimes called a bell curve but I don't like to use that term after some racist assholes wrote a book called that.)

The Basics of Normal Distribution

Normal distribution curves This graphic illustrates the two main characteristics of normal distribution. The first key figure is called the mean. You may also know it as the "average". It represents the most common value and is abbreviated with the Greek letter μ (mu). All of the curves in the example have a mean of 0 except the magenta one that has a mean of -2.

The other important figure is the standard deviation, abbreviated by the Greek letter σ (sigma). This indicates the width of the curve. Smaller standard deviations mean that values close to the mean will be more common, while larger values will make it more likely that results far from the mean can occur. Compare the red, green and blue curves. The rule of thumb is that about 68% of values will be within plus or minus 1 standard deviation from the mean. About 95% will be ± 2σ and about 99% will be ± 3σ.

Generating Standard Normal Distribution Programmatically

Most of the information out there about normal distribution involves calculating standard deviation and mean from a collection of data points. What we want to do is exactly the opposite. I read that the simplest way of doing this is to invert the standard normal cumulative distribution function. Yes, of course! It's so obvious! Wait, no. I have no idea what that means.

Maybe that is the simplest way for a mathematician to think about it, but it does not convert to a computer algorithm easily or efficiently. Several methods have been developed to solve this including the Box-Muller transform and the Ziggurat algorithm. I got a Box-Muller transform function working in JavaScript, but I still wanted to explore a few more methods. During my research, I developed my own method that is faster than Box-Muller and is conceptually so simple that I don't need to save a copy of it. I can just re-write when I need to. (The values it generates are not identical to the Box-Muller transform, but they are really, really close.)

Add Multiple Uniform Randoms

As you can see, I haven't thought of a snappy name for it yet.

An often forgotten thing about normal distribution is that its whole point is to simulate the effect of cumulative multiple random values. Adding a few random numbers together is a fairly simple procedure. I'd like to thank the mathematicians for making it so confusing.

function rnd_snd() { return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1); }

All I have done here is added three random numbers between -1 and 1 together. That will give a normal distribution with mean = 0 and standard deviation = 1. This is also called standard normal distribution. Try it out.

That function will return a decimal with an average value of 0, so it is not yet the figures we need to flesh out our fantasy characters. Fortunately, it is easy to get there from here. Multiply the result by the standard deviation that you want, then add your desired mean. Round the final result if you like. Below is a function I wrote to make that process a little easier.

function rnd(mean, stdev) { return Math.round(rnd_snd()*stdev+mean); }

Back to the fantasy babes. I'd like 95% of them to have chest measurements between 32" and 40" so I'll ask for a mean of 36 and a standard deviation of 2. Now you can generate a fantasy bust size.