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

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

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

person Community    schedule 20.08.2009    source источник


Ответы (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);
person DmitryK    schedule 20.08.2009
comment
Теперь я понял, что я хочу сформулировать благодаря вам.. Я хочу, чтобы -2*сигма.. +2*сигма были в начале и в конце диапазона (мин, макс) соответственно. - person ; 20.08.2009
comment
А, теперь я понимаю. Итак, вы хотите отойти от своего среднего значения влево и вправо и достичь минимума или максимума с достоверностью 95%. В этом случае вы сохраняете свое среднее значение, как оно есть (мин + (макс-мин)/2), но вам нужно рассчитать сигму (стандартное отклонение). Выход на 2*сигма дает нам этот 95% интервал. Таким образом, длина этого интервала равна 4*сигма. Но мы также можем рассчитать его как (max-min). Что дает нам sigma=(max-min)/4. Не могли бы вы попробовать это? - person DmitryK; 20.08.2009
comment
попасть в диапазон мин..макс с 95% уверенностью - просто чтобы быть точным в моей формулировке. - person DmitryK; 20.08.2009
comment
Это тоже работает, очень жаль, что я могу сделать только один ответ правильным. Stackoverflow должен добавить вспомогательные или общие ответы. - person ; 20.08.2009

person    schedule
comment
Да, это то, что BoxMuller (двойное среднее, двойное стандартное_отклонение) достигает выше. Проблема, однако, в том, что Next(int min, int max) возвращает значения, очень близкие к половине диапазона. Это потому, что я не понимаю, как правильно масштабировать отклонение. - person ; 20.08.2009
comment
Таким образом, для 3,5 стандартных отклонений это будет return (int)BoxMuller(min + (max-min)/2.0, (max-min)/2.0/3.5);? - person ; 20.08.2009
comment
Могу я просто прокомментировать, что +/- 3-кратное стандартное отклонение дает вам не 97%, а 99,7%. +/-сигма: ~68% +/-2сигма: ~95% +/-3сигма: ~99,7% en.wikipedia.org/wiki/68-95-99.7_rule - person DmitryK; 21.08.2009
comment
Спасибо, что указали на это, Дмитрий, моя статистика, видимо, немного заржавела. Я обновил ответ. - person Mark Rushakoff; 21.08.2009