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

В чем разница между srand (1) и srand (0)

Я только что обнаружил, что srand(1) сбрасывает PRNG из C (++) в состояние перед любым вызовом srand (как определено в reference). Тем не менее, семя 0, похоже, делает то же самое, или состояние до того, как любой вызов srand, кажется, использует семя 0. В чем разница между этими двумя вызовами или по какой причине они делают одно и то же?

Например, этот код (выполняется на Ideone)

#include <stdio.h>
#include <stdlib.h>

int main() {
    for (int seed = 0; seed < 4; seed++ ) {
        printf( "Seed %d:", seed);
        srand( seed );
        for(int i = 0; i < 5; i++ )
            printf( "    %10d", rand() );
        printf( "\n");
    }
    return 0;
}

возвращает

Seed 0:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 1:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 2:    1505335290    1738766719     190686788     260874575     747983061
Seed 3:    1205554746     483147985     844158168     953350440     612121425
4b9b3361

Ответ 1

Это, вероятно, деталь реализации. Стандарт предусматривает, что случайное семя 1 является особенным, а внутренний регистр вашего конкретного алгоритма случайного генератора, вероятно, инициализируется нулем, тем самым вызывая такую ​​же случайную последовательность для семян (0) и семян (1). Я даже ставлю, что первая строка вашей реализации srand() выглядит так:

if ( seed == 1 ) seed = 0;

для обеспечения стандартно-совместимого поведения.

Как правило, генераторы случайных чисел для rand() и srand() не обязаны давать разные последовательности для разных семян, но одну и ту же последовательность для одного и того же семени. Таким образом, не полагаются на разные семена, генерирующие разные случайные последовательности, и вы должны быть в порядке. Если нет, добро пожаловать в конкретную забаву.

Ответ 2

Как работает glibc:

вокруг строки 181 glibc/stdlib/random_r.c, внутри функции __srandom_r

  /* We must make sure the seed is not 0.  Take arbitrarily 1 in this case.  */
  if (seed == 0)
    seed = 1;

Но это то, как это делает glibc. Это зависит от реализации стандартной библиотеки C.

Ответ 3

Ни стандарты C, ни С++ не говорят о специфике реализации rand() и srand(). Детали остаются почти полностью до разработчика. Стандарт C требует, чтобы:

Если srand затем вызывается с тем же начальным значением, последовательность псевдослучайных чисел должна повторяться. Если rand вызывается до того, как были сделаны вызовы srand, одна и та же последовательность должна быть сгенерирована так, как когда srand сначала вызывается с начальным значением 1.

но он не содержит требования о том, чтобы разные семена должны создавать разные последовательности. По-видимому, в вашей системе семена нулевого и одного имеют тот же эффект. Я предполагаю, что это должно обеспечить обратную совместимость с некоторым программным обеспечением, которое ожидает от srand(0) до reset PRNG до его начального состояния.

Ответ 4

Если для семени установлено значение 1, генератор повторно инициализируется до его начального значения и выдает те же значения, что и перед любым вызовом rand или srand. Взято из srand ссылка

Ответ 5

При чтении страниц руководства все они утверждают, что "Если не задано начальное значение, функция rand() автоматически засевается значением 1." Вероятно, поэтому ссылка на ссылку, на которую ссылается, указывает, что посев с 1 сбрасывает состояние.

То же самое происходит при посеве с 0 и 1, скорее всего, зависит от реализации и не должно учитываться на всех платформах.

Ответ 6

Функция srand() использует этот аргумент как семя для новой последовательности псевдослучайных чисел, которые будут возвращены последующими вызовами rand(). Если srand() вызывается с тем же начальным значением, последовательность псевдослучайных чисел должна повторяться. Если вызов rand() вызывается до того, как сделаны какие-либо вызовы srand(), одна и та же последовательность должна быть сгенерирована так, как когда srand() сначала вызывается с начальным значением 1.

Возможно, полезно: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

Ответ 7

Причина 1 указана в том, что некоторые генераторы случайных чисел будут застревать в нуле, если семя будет установлено на ноль. Например, сдвиговые регистры и мультипликативные конгруэнтные типы, т.е. r(n+1) = (A * r(n))mod M.

Многие реализации C используют линейные конгруэнтные r(n+1) = (A * r(n) + B) mod M, B < > 0, которые не застревают.