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

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

Я понимаю, что нормальное распределение уходит в + бесконечность. Я предполагаю, что хвосты могут быть отсечены, поэтому, когда случайное число вычисляется за пределами диапазона, пересчитайте. Это увеличивает вероятность целых чисел в диапазоне, но до тех пор, пока этот эффект терпим (<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;
    }

Ответы на вопрос(2)

сигма -2 *. + 2 * даст вам 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);
 John Smith20 авг. 2009 г., 04:10
Теперь я понимаю, что я хочу сформулировать, благодаря вам .. Я хочу, чтобы сигма -2 * сигма .. + 2 * была в начале и в конце диапазона (мин, макс) соответственно.
 DmitryK20 авг. 2009 г., 06:56
удар" в диапазоне min..max с доверием 95% - просто чтобы быть точным в моей формулировке.
 John Smith20 авг. 2009 г., 18:39
Это тоже работает, жаль, что я могу сделать только один правильный ответ. Stackoverflow должен добавить "помощь» или же "общий" ответы.
 DmitryK20 авг. 2009 г., 06:55
Ах, теперь я понимаю. Таким образом, вы хотите выйти из среднего значения влево и вправо и "удар" либо мин, либо макс с вероятностью 95%. В этом случае - вы сохраняете среднее значение в том виде, в котором оно у вас есть (мин + (макс-мин) / 2), но вам необходимо вычислить сигму (стандартное отклонение). Выход на 2 * сигма дает нам этот 95% интервал. Таким образом, длина этого интервала составляет 4 * сигма. Но мы также можем рассчитать его как (макс-мин). Что дает нам сигма = (макс-мин) / 4. Можете ли вы попробовать это? "
Решение Вопроса

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

УвидетьСтатья в википедииРаздел s по нормализации стандартных нормальных переменных (свойство 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)

 John Smith20 авг. 2009 г., 18:37
Так что для 3,5 стандартных отклонений это было быreturn (int) BoxMuller (min + (max - min) / 2.0, (max - min) / 2.0 / 3.5); "?
 John Smith20 авг. 2009 г., 02:56
Да, это то, что BoxMuller (double mean, double standard_deviation) достигает выше. Проблема, однако, заключается в том, что Next (int min, int max) возвращает значения, очень близкие к половине пути. Это потому что я нене понимаю, какмасштаб" отклонение правильно.
 DmitryK21 авг. 2009 г., 01:55
Могу я просто прокомментировать, что +/- 3 раза стандартное отклонение дает вам не 97%, а 99,7%. +/- сигма: ~ 68% +/- 2 сигма: ~ 95% +/- 3 сигма: ~ 99,7%en.wikipedia.org/wiki/68-95-99.7_rule
 Mark Rushakoff21 авг. 2009 г., 03:18
Спасибо, что указал на это, Дмитрий - моя статистика была немного ржавой, по-видимому. Я обновил ответ.

Ваш ответ на вопрос