首页 > 解决方案 > 使用 box-muller 方法生成随机标准正态分布数

问题描述

我需要生成介于 0 和 1 之间的随机标准正态分布数,均包含在均值 0 和标准开发 1 中。问题是虽然代码正在工作,但生成的随机数不在 0 和 1 之间。

这是使用 Box-muller 算法的方法:

public double NextGaussian()
    {
            double u1 = r.NextDouble();
            double u2 = r.NextDouble();
            double left = Math.Cos(2.0 * Math.PI * u1);
            double right = Math.Sqrt(-2.0 * Math.Log(u2));
            double z = left * right;
            return this.mean + (z * this.standardDeviation);          
    }

然后在main方法中:

Gaussian g = new Gaussian(0.0, 1.0);
double a = g.NextGaussian();

我希望变量 a 的值都在 0 和 1 之间,但实际输出都是数字

标签: c#gaussian

解决方案


我认为您的问题在于对正态分布的误解。正态分布为您提供范围内的数字(-inf, inf)。虽然绝对值越大,这个数字就越不可能(不是线性的)。您可以在正态分布的每张图片上看到这一点。简而言之,平均值是最高概率的值,标准偏差定义了曲线的峰值程度,

由于您只需要[mean, mean + standard dev]i 中的值,因此建议稍微调整分布并使用随机数的绝对值(相对于均值)并将其切割为标准偏差,将此值视为mean + standart dev.

public static double NextRandomWithinStandardDeviation(this Gaussian gaussian)
{
    return Math.Min(
        Math.Abs(gaussian.NextRandom() - gaussian.Mean) + gaussian.Mean,
        gaussian.Mean + gaussian.StandardDeviation
    );
}

然而,这不会是真正的正态分布。事实上,所有生成的随机数中有 21.73% 会超出您的区间,这会提高获得mean + standard deviation显着的概率。

另一种方法可能是生成随机数,直到生成的数字在区间内。理论上这可能需要很长时间,但在第五次迭代后得到一个超出区间的数字的概率小于 0.01%。

public static double NextRandomWithinStandardDeviation(this Gaussian gaussian)
{
    double randomNumer;
    do
    {
        randomNumber = Math.Abs(gaussian.NextRandom() - gaussian.Mean) + gaussian.Mean;
    }while(randomNumber > gaussian.Mean + gaussian.StandardDeviation);

    return randomNumber;
}

推荐阅读