Nonuniform Random Number Generators
June 10, 2009
A nice R feature that I haven’t seen in any other language is random number generators for distributions other than the uniform distribution. The most useful is the normal distribution: here’s a crude simulation of rnorm in ruby
def rnorm(mean=0, sd=1)
coin_flips=37
binomial = Array.new(coin_flips) { rand(2) }.inject { |m,o| m+o }
zscore = 2 * (binomial - (coin_flips/2))/coin_flips**0.5
zscore * sd + mean
end
and in javascript:
function rnorm(mean,sd) {
coin_flips=37;
if (null == mean) { mean = 0; }
if (null == sd) { sd = 1;}
binomial=0;
for(i=0;i < coin_flips; i++) {
if ( 0.5 < Math.random() ) {
binomial += 1;
}
}
zscore = 2 * (binomial - (coin_flips/2))/Math.pow(coin_flips,0.5);
return zscore * sd + mean;
}
Unlike the R version, there are only 38 possible values that above functions can assume, which might not be acceptable if repeated trials are being made. To fix that, here is a ruby version which mixes in another random number.
def fuzz(width)
[(rand-0.5)*width, ((width**2)/12.0)**0.5]
end
def rnorm(mean=0, sd=1)
coin_flips=37
fuzz, fuzz_sd = fuzz(1/coin_flips**0.5)
binomial = Array.new(coin_flips) { rand(2) }.inject { |m,o| m+o }
zscore = 2 * (binomial - (coin_flips/2))/coin_flips**0.5
zscore * (sd**2-fuzz_sd**2)**0.5 + mean + fuzz
end