Как создать нормально распределенное случайное из целочисленного диапазона?

Учитывая начало и конец целочисленного диапазона, как я могу рассчитать нормально распределенное случайное целое число между этим диапазоном?

Я понимаю, что нормальное распределение переходит в + бесконечность. Я думаю, что хвосты могут быть обрезаны, поэтому, когда случайные вычисления вычисляются вне диапазона, пересчитайте. Это повышает вероятность целых чисел в диапазоне, но до тех пор, пока этот эффект является допустимым (< 5%), он прекрасен.

public class Gaussian { private static bool uselast = true; private static ****** next_gaussian = 0.0; private static Random random = new Random(); public static ****** BoxMuller() { if (uselast) { uselast = false; return next_gaussian; } else { ****** v1, v2, s; do { v1 = 2.0 * random.**********() - 1.0; v2 = 2.0 * random.**********() - 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 ****** BoxMuller(****** mean, ****** 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)
 {
 ****** 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 ответа

Если метод Box-Muller возвращает стандартное нормальное распределение, оно будет иметь среднее значение 0 и стандартное отклонение 1. Чтобы преобразовать стандартное нормальное распределение, вы умножаете свое случайное число на X, чтобы получить стандартное отклонение X, и вы добавляете Y, чтобы получить среднее значение Y, если память служит мне правильно.

См. раздел статьи Википедии о нормализации стандартных нормальных переменных (свойство 1) для более формального доказательства.

В ответ на ваш комментарий эмпирическое правило состоит в том, что 99,7% от нормального распределения будет в пределах +/- 3 раза от стандартного отклонения. Если вам требуется нормальное распределение от 0 до 100, например, ваше среднее будет на полпути, а ваш SD будет (100/2)/3 = 16,667. Итак, какие бы значения вы ни выбрали из вашего алгоритма Box-Muller, умножьте на 16.667, чтобы "растянуть" дистрибутив, затем добавьте 50 к "центру".

Джон, в ответ на ваш новый комментарий, я действительно не уверен, в чем смысл функции Next. Он всегда использует стандартное отклонение 1 и среднее на полпути между вашим минимумом и максимумом.

Если вам нужно среднее значение Y, с ~ 99,7% от числа в диапазоне от -X до + X, вы просто вызываете BoxMuller(Y, X/3).


Ну, сигма -2 * сигма.. + 2 * даст вам 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);

licensed under cc by-sa 3.0 with attribution.