正規分布乱数
平均 \(\mu\), 標準偏差 \(\sigma\) の正規分布乱数を得るために、Box-Muller法という手法があります。この手法は、\( \alpha, \beta\) を [0,1]範囲の一様乱数としたとき、次の二つの数値
- \(\sqrt{-\ln{\alpha^{2}}} \sin{ 2\pi\beta}\)
- \(\sqrt{-\ln{\alpha^{2}}} \cos{ 2\pi\beta}\)
が 平均値0, 標準偏差1の正規分布に即した乱数になるという性質を利用します。[0,1]範囲の一様乱数を二回発生することになりますが、上記の二つの数値に相関はないため、二つの正規分布乱数が得られることになります。
得られた数値に \(\sigma\) をかけた後、\(\mu\) を足せば、任意の正規分布乱数の出来上がりです。
以下にC#のコード載せておきます。
// 平均mu, 標準偏差sigmaの正規分布乱数を得る。Box-Muller法による。
public static double NormalDistribution(double mu, double sigma)
{
if (Flag)
{
Alpha = Rn.NextDouble();
Beta = Rn.NextDouble() * Math.PI * 2;
BoxMuller1 = Math.Sqrt(-2 * Math.Log(Alpha));
BoxMuller2 = Math.Sin(Beta);
}
else
BoxMuller2 = Math.Cos(Beta);
Flag = !Flag;
return sigma * (BoxMuller1 * BoxMuller2) + mu;
}
static Random Rn = new Random(System.Environment.TickCount);
static double Alpha, Beta, BoxMuller1, BoxMuller2;
static bool Flag = false;
対数正規分布関数
次は、対数正規分布乱数についてです。対数正規分布とは横軸 (\(X\) 軸)を対数に変換すると正規分布に従うような分布のことです。
まず、普通の正規分布関数 \(f(x)\) の平均値を \(m\), 標準偏差を \(s\) とします。さらに、この関数の横軸を対数に変換した時の平均値 (つまり\(\ln(x)\)の平均)を \(\mu\), 標準偏差( \(\ln(x)\)の標準偏差)を \(\sigma\) とします。\(m, s, \mu, \sigma\) の間には以下のような関係があります。
- \( m=\exp{(\mu + \sigma^2/2)}\)
- \(s=m^2 (\exp{(\sigma^2/2) -1})\)
\(\mu\) と \(\sigma\) を左辺にすると
- \(\mu = \ln{m^2} – \frac{ \ln{(m^2+s^2)} }{2}\)
- \(\sigma= \sqrt{ \ln{(1+\frac{s^2}{m^2})} }\)
となります。この性質を利用すると、対数正規分乱数を発生するコードは以下のようにかけます。
//平均mu, 標準偏差sigmaの対数正規分布乱数を得る。
//平均と標準偏差を変換し、Box-Muller法によるNormlDistribution関数を呼び出す。
public static double LogNormalDistribution(double mu, double sigma)
{
if (mu <= 0)
return double.NaN;
else
{
var sigma2= sigma * sigma;
var val = NormalDistribution(Math.Log(mu) - Math.Log(mu + sigma2) / 2.0, Math.Sqrt(Math.Log(1 + sigma2 / mu / mu)));
return Math.Exp(val);
}
}