Использование qsrand, случайный метод, который не является случайным - PullRequest
18 голосов
/ 04 мая 2010

У меня здесь странная проблема, и я не могу найти хорошее объяснение этому, поэтому я подумал спросить вас, ребята:

Рассмотрим следующий метод:

int MathUtility::randomize(int Min, int Max)
{
    qsrand(QTime::currentTime().msec());

    if (Min > Max)
    {
        int Temp = Min;
        Min = Max;
        Max = Temp;
    }
    return ((rand()%(Max-Min+1))+Min);
}

Я не буду объяснять вам, гуру, что на самом деле делает этот метод, я вместо этого объясню свою проблему:

Я понял, что когда я вызываю этот метод в цикле, иногда , я снова и снова получаю одно и то же случайное число ... Например, этот фрагмент ...

for(int i=0; i<10; ++i)
{
    int Index = MathUtility::randomize(0, 1000);
    qDebug() << Index;
}

... выдаст что-то вроде:

567 567 567 567 ... и т.д. ...

Я тоже понял, что, если я не вызываю qsrand каждый раз, а только один раз за время жизни моего приложения, он работает отлично ...

Мой вопрос: почему?

Ответы [ 6 ]

36 голосов
/ 04 мая 2010

Поскольку, если вы вызываете randomize более одного раза в миллисекунду (что весьма вероятно при текущих тактовых частотах процессора), вы заполняете RNG с тем же значением. Это гарантировано для получения того же результата от ГСЧ.

Генераторы случайных чисел должны быть посеяны только один раз. Посев их несколько раз не делает вывод более случайным, и фактически (как вы обнаружили) может сделать его намного меньше случайным.

2 голосов
/ 14 февраля 2012

Если вы вызываете функцию qsrand Qt для инициализации начального числа, вы должны вызвать функцию qrand Qt для генерации случайного числа, а не функции rand из стандартной библиотеки. инициализация семени для функции rand - srand. Извините за раскопки.

2 голосов
/ 04 мая 2010

Если вы сделаете вызов достаточно быстро, значение QTime::currentTime().msec() не изменится, и вы в основном повторно набираете qsrand с тем же начальным числом, в результате чего следующее сгенерированное случайное число будет таким же, как и предыдущее .

1 голос
/ 04 мая 2010

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

0 голосов
/ 10 февраля 2018

Я нашел то же действие и решил его, используя rand() вместо srand().

Но я использую его для проверки своего приложения. Это просто работает в цикле, поэтому мне не нужно искать его обновления.

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

0 голосов
/ 19 сентября 2014

Две проблемы:

1 Как уже отмечали другие, генератор засеивается несколько раз.

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

Вы предполагаете, что младшие биты от генератора распределены равномерно. Это не относится к большинству генераторов. В большинстве генераторов случайность встречается в старших разрядах.

Используя остаток после деления, вы фактически выбрасываете случайность.

Вы должны масштабировать, используя умножение и деление. Не используется оператор по модулю. например,

my_number = start_required + (generator_output * range_required) / generator_maximum;

если generator_output находится в [0, generator_maximum] my_number будет в [start_required, start_required + range_required]

...