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

我意识到正态分布进入 - +无穷大。我想尾巴可能会被切断,因此,当随机计算出范围之外时,请重新计算。这可以提高整数在该范围内的概率,但是只要这种效果是可以忍受的(<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;
    }
有帮助吗?

解决方案

如果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个标准偏差为1,平均值在您的最小值和最大值之间。

如果您想要y的平均值,在范围-x至 +x范围内的数字的〜99.7%,则只需致电 BoxMuller(Y, X/3).

其他提示

好吧,-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);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top