Генерация случайного стандартного нормального числа распределения с использованием метода Бокса-Мюллера - PullRequest
0 голосов
/ 09 января 2019

Мне нужно сгенерировать случайные стандартные числа нормального распределения между 0 и 1, включенные со средним значением 0 и стандартным dev 1. Проблема заключается в том, что, хотя код работает, генерируемые случайные числа не находятся между 0 и 1.

Это метод, использующий алгоритм Бокса-Мюллера:

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

Тогда в основном методе:

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

Я ожидаю, что переменная a будет иметь значение между 0 и 1, но в действительности все числа

1 Ответ

0 голосов
/ 10 января 2019

Я думаю, что ваша проблема заключается в неправильном понимании нормального распределения. Нормальное распределение дает вам числа в диапазоне (-inf, inf). Хотя чем больше абсолютное значение, тем менее вероятным является число (не линейное). Вы можете видеть это на каждой картине нормального распределения. Проще говоря, среднее значение является значением самой высокой вероятности, а стандартное отклонение определяет, насколько пиковой является кривая,

Поскольку вам нужны только значения в [mean, mean + standard dev], я рекомендую немного настроить распределение и использовать абсолютное значение случайного числа (по отношению к среднему значению) и вырезать его при стандартном отклонении, рассматривая это значение как значение 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;
}
...