如何从整数范围生成正态分布随机?

时间:2009-08-20 00:33:27

标签: c# random range gaussian normal-distribution

给定整数范围的开始和结束,如何计算此范围之间的正态分布随机整数?

我意识到正态分布会进入 - +无穷大。我猜尾巴可以被截断,所以当一个随机数被计算到范围之外时,重新计算。这提高了范围内整数的概率,但只要这种效果是可以容忍的(<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;
    }

2 个答案:

答案 0 :(得分:6)

如果Box-Muller方法返回“标准”正态分布,则它将具有平均值0和标准差1.要转换标准正态分布,将随机数乘以X得到标准偏差X,然后添加Y如果记忆正确地为我服务,则获得平均值Y.

请参阅Wikipedia article's section on normalizing standard normal variables (property 1)以获取更正式的证明。


根据您的评论,经验法则是99.7%的正态分布将在标准差的+/- 3倍之内。例如,如果您需要从0到100的正态分布,那么您的平均值将是中途,并且您的SD将是(100/2)/ 3 = 16.667。因此,无论你使用Box-Muller算法得到什么值,都要乘以16.667来“拉伸”分布,然后将50加到“中心”。


John,为了回应你的最新评论,我真的不确定Next功能有什么意义。它始终使用标准偏差1和平均值在最小值和最大值之间。

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

答案 1 :(得分:1)

嗯,-2 * sigma .. + 2 * sigma会给你95%的钟形曲线。 (查看已经提到的维基文章中的“标准偏差和置信区间”部分)。

所以修改这篇文章:

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);