Normal Random
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.
Limitations
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.
##Installation
I’ve packaged this code as a gem, so just:
gem install normal_random
And you’re off!