10

整数範囲の開始と終了が与えられた場合、この範囲の間に正規分布のランダム整数を計算するにはどうすればよいですか?

正規分布が-+無限大になることを理解しています。テールをカットオフできると思うので、ランダムが範囲外で計算された場合は、再計算します。これにより、範囲内の整数の確率が高くなりますが、この効果が許容できる(<5%)限り、問題ありません。

public class Gaussian
{
    private static bool uselast = true;
    private static double next_gaussian = 0.0;
    private static Random random = new Random();

    public static double BoxMuller()
    {
        if (uselast) 
        { 
            uselast = false;
            return next_gaussian;
        }
        else
        {
            double v1, v2, s;
            do
            {
                v1 = 2.0 * random.NextDouble() - 1.0;
                v2 = 2.0 * random.NextDouble() - 1.0;
                s = v1 * v1 + v2 * v2;
            } while (s >= 1.0 || s == 0);

            s = System.Math.Sqrt((-2.0 * System.Math.Log(s)) / s);

            next_gaussian = v2 * s;
            uselast = true;
            return v1 * s;
        }
    }

    public static double BoxMuller(double mean, double standard_deviation)
    {
        return mean + BoxMuller() * standard_deviation;
    }

    public static int Next(int min, int max)
    {
        return (int)BoxMuller(min + (max - min) / 2.0, 1.0); 
    }
}

おそらく、範囲に対して標準偏差をある程度スケーリングする必要がありますが、その方法がわかりません。

答え:

    // Will approximitely give a random gaussian integer between min and max so that min and max are at
    // 3.5 deviations from the mean (half-way of min and max).
    public static int Next(int min, int max)
    {
        double deviations = 3.5;
        int r;
        while ((r = (int)BoxMuller(min + (max - min) / 2.0, (max - min) / 2.0 / deviations)) > max || r < min)
        {
        }

        return r;
    }
4

2 に答える 2

6

Box-Muller 法が「標準」正規分布を返す場合、平均は 0、標準偏差は 1 になります。標準正規分布を変換するには、乱数に X を掛けて標準偏差 X を取得し、Y を加算して取得します。メモリが正しく機能する場合は、Y を意味します。

より正式な証明については、ウィキペディアの記事の標準正規変数 (プロパティ 1) の正規化に関するセクションを参照してください。


あなたのコメントに応えて、経験則では、正規分布の 99.7% は標準偏差の +/- 3 倍以内になります。たとえば、0 から 100 までの正規分布が必要な場合、平均は半分になり、SD は (100/2)/3 = 16.667 になります。したがって、Box-Muller アルゴリズムから得られる値が何であれ、16.667 を掛けて分布を「引き延ばし」、次に 50 を加えて分布を「中央」にします。


ジョン、あなたの最新のコメントに応えて、関数のポイントが本当にわかりませんNext. 常に 1 の標準偏差と、最小値と最大値の中間の平均値を使用します。

-X から +X の範囲の数値の ~99.7% で、Y の平均が必要な場合は、 を呼び出すだけBoxMuller(Y, X/3)です。

于 2009-08-20T00:48:50.117 に答える
2

-2*sigma..+2*sigma はベル曲線の 95% を提供します。(すでに言及されているwiki記事の「標準偏差と信頼区間」セクションを確認してください)。

したがって、この部分を変更します。

return (int)BoxMuller(min + (max - min) / 2.0, 1.0);

1.0 (標準偏差) を 2.0 (または 95% 以上のカバレッジが必要な場合はさらに) に変更します。

return (int)BoxMuller(min + (max - min) / 2.0, 2.0);
于 2009-08-20T01:31:38.720 に答える