Random number generators are generally uniform, ie. any number inside the range is equally likely to be chosen. But what if you’re generating numbers that need to fall along a normal curve? For example, what if you’re generating people for a game and those people have IQ scores?
IQ has a mean of 100 and a standard deviation of 15. How do I generate a population of people in which the IQ distribution is realistic?
class NormalRandom DEFAULT_MU = 100 DEFAULT_SIGMA = 15 attr_accessor :rng def initialize self.rng = Random.new end def rand(mu = DEFAULT_MU, sigma = DEFAULT_SIGMA) (standard_deviations * sigma) + mu end def box_muller Math.sqrt(-2*Math.log(rng.rand))*Math.cos(2*Math::PI*rng.rand) end alias_method :standard_deviations, :box_muller end
This is an implementation of the Box-Muller Transformation which is one of the standard methods of generating normally distributed numbers.
Box-Muller is limited to generating numbers at most 6 standard deviations from the mean. That is, the best score possible from this class is at the 99.9999998752th percentile. For most purposes that’s fine.
The other thing is that the Box-Muller algorithm is slower than the Ziggurat algorithm. Ziggurat, however, requires a table of values to work, and it’s more complex. My goal with this class was to be as bonehead simple as I possibly could be.
I’ve packaged this code as a gem, so just:
gem install normal_random
And you’re off!