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,如果我没记错的话。

有关更正式的证明,请参阅Wikipedia 文章中关于标准化标准正态变量(属性 1)的部分。


针对您的评论,经验法则是 99.7% 的正态分布将在标准偏差的 +/- 3 倍范围内。例如,如果您需要从 0 到 100 的正态分布,那么您的平均值将是一半,您的 SD 将是 (100/2)/3 = 16.667。因此,无论您从 Box-Muller 算法中得到什么值,乘以 16.667 以“拉伸”分布,然后加上 50 以使其“居中”。


约翰,针对您的最新评论,我真的不确定该Next功能的意义何在。它始终使用 1 的标准偏差和最小值和最大值之间的平均值。

如果你想要 Y 的平均值,大约 99.7% 的数字在 -X 到 +X 的范围内,那么你只需调用BoxMuller(Y, X/3).

于 2009-08-20T00:48:50.117 回答
2

Well, the -2*sigma..+2*sigma will give you 95% of the bell curve. (check the "Standard deviation and confidence intervals" section in the already mentioned wiki article).

So modify this piece:

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

and change 1.0 (standard deviation) to 2.0 (or even more if you want more than 95% coverage)

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