Как генерировать нормально распределенный случайный из целочисленного диапазона?
-
19-09-2019 - |
Вопрос
Учитывая начало и конец целочисленного диапазона, как я могу рассчитать обычно распределенное случайное целое число между этим диапазоном?
Я понимаю, что нормальное распределение переходит в -+ бесконечность. Я предполагаю, что хвосты могут быть отсечены, поэтому, когда случайный вычисляется вне диапазона, перечисляется. Это повышает вероятность целых чисел в диапазоне, но до тех пор, пока этот эффект терпим (<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;
}
Решение
Если метод склада вставки возвращает «стандартное» нормальное распределение, он будет иметь среднее значение 0 и стандартное отклонение 1. Чтобы преобразовать стандартное нормальное распределение, вы умножаете свое случайное число на x, чтобы получить стандартное отклонение x и добавить Y, чтобы получить Значит y, если память служит мне правильно.
Увидеть Раздел статьи Википедии о нормализации стандартных нормальных переменных (свойство 1) для более формального доказательства.
В ответ на ваш комментарий правило, что 99,7% от нормального распределения будет в пределах +/- 3 раза превышать стандартное отклонение. Например, если вам нужно нормальное распределение от 0 до 100, то ваше среднее будет на полпути, а ваш SD будет (100/2)/3 = 16,667. Таким образом, любые значения, которые вы получаете из своего алгоритма, умножьте на 16.667, чтобы «растянуть» распределение, а затем добавьте 50 в «Центр» его.
Джон, в ответ на ваш новый комментарий, я действительно не уверен, в чем смысл Next
функция Он всегда использует стандартное отклонение 1 и среднее значение на полпути между вашим минимальным и максимум.
Если вы хотите среднего y, с ~ 99,7% чисел в диапазоне от -x до +x, то вы просто вызываете BoxMuller(Y, X/3)
.
Другие советы
Ну, -2*Sigma ..+2*Sigma даст вам 95% кривой колокола. (Проверьте раздел «Стандартные отклонения и доверительные интервалы» в уже упомянутой статье вики).
Так что измените эту часть:
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);