Ради интереса довольно просто сгенерировать нормально распределенные случайные числа из единого ГСЧ (хотя это должно быть сделано парами):
Random rng = new Random();
double r = Math.Sqrt(-2 * Math.Log(rng.NextDouble()));
double θ = 2 * Math.Pi * rng.NextDouble();
double x = r * Math.Cos(θ);
double y = r * Math.Sin(θ);
x
и y
теперь содержат два независимых, нормально распределенных случайных числа со средним значением 0 и дисперсией 1. Вы можете масштабировать и переводить их по мере необходимости, чтобы получить нужный диапазон (как объясняет междурядье).
Пояснение:
Этот метод называется преобразованием Бокса-Мюллера . Он использует свойство двумерной единицы Гаусса, состоящее в том, что само значение плотности, p = exp(-r^2/2)
, равномерно распределено между 0
и 1
(константа нормализации удалена для простоты).
Поскольку вы можете легко сгенерировать такое значение, используя однородный ГСЧ, вы получите круговой контур радиуса r = sqrt(-2 * log(p))
. Затем вы можете сгенерировать вторую равномерную случайную величину между 0
и 2*pi
, чтобы получить угол θ
, который определяет уникальную точку на вашем круговом контуре. Наконец, вы можете сгенерировать два i.i.d. нормальных случайных изменения путем преобразования из полярных координат (r, θ)
обратно в декартовы координаты (x, y)
.
Это свойство - равномерно распределенное p
- не распространяется на другие измерения, поэтому вам нужно генерировать ровно две нормальные переменные одновременно.