正規分布(ガウス分布)の乱数を作り出す方法として、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乗くらいあるので、まったくでないというほどでもない気がする。