正規分布の乱数の生成方法

2013-05-08

正規分布(ガウス分布)の乱数を作り出す方法として、Box-Muller法というものがあるらしい。XとYを一様乱数として

でZ1とZ2に2つの独立した正規分布の乱数が得られるとか。sinとcosを使っているのに独立してるとか、不思議。コードにするとこんな感じか:

class Random
@@gnext = nil

def self.gauss
if @@gnext
r = @@gnext
@@gnext = nil
return r
else
x = rand
y = rand
sqrt_minus_2_logx = Math.sqrt(-2 * Math.log(x))
two_pi_y = 2 * Math::PI * y
z1 = sqrt_minus_2_logx * Math.cos(two_pi_y)
z2 = sqrt_minus_2_logx * Math.sin(two_pi_y)
@@gnext = z2
return z1
end
end
end

それとは別に、簡易的な方法として0.0〜1.0の一様乱数を12個足して-6.0してもいいらしい。0〜1の一様乱数の分散は1/12なのでそれを12個足し合わせると分散が1になるとかなんとか。

この方法の場合、-6以下または6以上の値は絶対に返らないけどいいのかな。正規分布で6.0のときの値は6.08e-09で、-6〜6以外の値が出る確率も10の-7乗くらいあるので、まったくでないというほどでもない気がする。