Подтвердить что ты не робот

Случайное число в пределах диапазона, основанного на нормальном распределении

Я хочу генерировать случайные числа с диапазоном (от n до m, например от 100 до 150), но вместо чисто случайного я хочу, чтобы результаты были основаны на нормальном распределении.

Под этим я подразумеваю, что в целом я хочу, чтобы числа "сгруппированы" около 125.

Я нашел этот пакет случайных чисел, который, кажется, имеет много чего мне нужно: http://codeproject.com/KB/recipes/Random.aspx

Он поддерживает множество случайных генераторов (включая mersiene twister) и может применять генератор к распределению.

Но я смущен, если я использую обычный генератор распределения, случайные числа от примерно -6 до +8 (видимо, истинным диапазоном является float.min to float.max).

Как масштаб, который соответствует моему диапазону?

4b9b3361

Ответ 1

Стандартное нормальное распределение имеет среднее значение 0 и стандартное отклонение 1; если вы хотите сделать распределение со средним значением m и отклонение s, просто умножьте на s, а затем добавьте m. Поскольку нормальное распределение теоретически бесконечно, вы не можете иметь жесткий колпачок на вашем диапазоне, например. (От 100 до 150) без явного отказа от числа, выходящего за его пределы, но при соответствующем выборе отклонения вы можете быть уверены, что (например, 99% ваших номеров будут находиться в пределах диапазона.

Около 99,7% населения находится в пределах +/- 3 стандартных отклонений, поэтому, если вы выберете ваш размер около (25/3), он должен хорошо работать.

Итак, вы хотите что-то вроде: (normal * 8.333) + 125

Ответ 2

Для интереса довольно просто создать нормально распределенные случайные числа из однородного RNG (хотя это должно быть сделано парами):

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. Вы можете масштабировать и переводить их по мере необходимости, чтобы получить желаемый диапазон (как поясняет interjay).


Объяснение:

Этот метод называется Преобразование Box-Muller. Он использует свойство двумерной единицы Гаусса, что само плотность плотности p = exp(-r^2/2) равномерно распределяется между 0 и 1 (константа нормализации удалена для простоты).

Поскольку вы можете легко генерировать такое значение, используя единый RNG, вы получите круговой контур радиуса r = sqrt(-2 * log(p)). Затем вы можете создать вторую равномерную случайную величину между 0 и 2*pi, чтобы дать вам угол θ, который определяет уникальную точку на вашем круговом контуре. Наконец, вы можете генерировать два i.i.d. нормальные случайные вариации путем преобразования из полярных координат (r, θ) обратно в декартовы координаты (x, y).

Это свойство - равномерное распределение p - не выполняется для других размерностей, поэтому вы должны генерировать ровно два нормальных значения за раз.

Ответ 3

Ответ tzaman правильный, но при использовании библиотеки, которую вы связали, есть более простой способ, чем выполнить вычисление самостоятельно. Объект NormalDistribution имеет свойства записи Mu (что означает среднее значение) и Sigma (стандартное отклонение), Итак, перейдя по номерам tzaman, установите Mu на 125 и Sigma на 8.333.

Ответ 4

Это может быть слишком упрощенным для ваших нужд, но быстрый и дешевый способ получить случайное число с распределением, взвешенным по центру, - это просто добавить 2 (или более) случайных числа.

Подумайте, когда вы катите две 6-сторонние кости и добавляете их. Сумма чаще всего равна 7, затем 6 и 8, затем 5 и 9 и т.д. И только редко 2 или 12.

Ответ 5

В другом подходе к этой проблеме используется бета-дистрибутив (в отличие от нормального распределения), и включает в себя выбор подходящих параметров, чтобы распределение имело заданное среднее и стандартное отклонение (квадратный корень дисперсии). См. этот вопрос.

Ответ 6

Здесь другой алгоритм, который не нужно вычислять Sin/Cos, и не нужно знать Pi. Не спрашивайте меня о теоретическом фоне. Я нашел его где-то один раз и это то, что я использовал с тех пор. Я подозреваю, что это какая-то нормализация того же преобразования Box-Muller, что @Wous Vousden упоминает. Он также дает результаты в парах.

Пример: VBscript; достаточно легко конвертировать в любой другой язык.

Sub calcRandomGauss (byref y1, byref y2)
    Dim x1, x2, w
    Do
        x1 = 2.0 * Rnd() - 1.0
        x2 = 2.0 * Rnd() - 1.0
        w = x1 * x1 + x2 * x2
    Loop While w >= 1.0 Or w = 0  'edited this line, thanks Richard

    w = Sqr((-2.0 * Log(w)) / w )
    y1 = x1 * w
    y2 = x2 * w
End Sub