Как srand относится к функции rand?

Я понимаю, что функция rand() генерирует одинаковое число (число), которое вы запускаете, если вы не меняете номер семени. То, что приходит srand(). Время всегда меняется, поэтому я знаю, что вы должны передать параметр времени (null) в srand. Мой вопрос связан с приведенным ниже кодом с учебного сайта.

int main()
{
    int i, n=5;
    time_t t;

    /* Intializes random number generator */
    srand((unsigned) time(&t));

    /* Print 5 random numbers from 0 to 50 */
    for( i = 0 ; i < n ; i++ ) {
        printf("%d\n", rand() % 50);
    }

    return(0);
}

Я не вижу ссылки из srand

((unsigned) time(&t)); 

и rand.

printf("%d\n", rand() % 50);

Где связь между rand и srand? Я имею в виду или ожидаю, что я предполагаю, что rand() получит некоторый параметр из srand(), чтобы он каждый раз генерировал разные числа. Я предполагаю, что это будет выглядеть как rand (srand (time (null));

Это похоже на инициализацию переменной, не используя ее для меня. srand инициализируется, но я не вижу, чтобы он использовался.

Производит ли rand разные числа, потому что srand вызывается первым перед rand?

Ответы

Ответ 1

Число случайных чисел - это глобальная статическая переменная. rand и srand оба имеют к нему доступ.

Ответ 2

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

Много кода использует текущее время в качестве семени, чтобы заставить каждую программу работать с другой последовательностью случайных чисел, но вы всегда можете изменить ее на srand(42) во время отладки в целях повторяемости. И вызов time() на самом деле не нужен переменная для размещения времени в, вы можете просто передать NULL:

srand (time (NULL));

Все это может быть реализовано в одном файле с чем-то вроде следующего: пример, приведенный в стандарте (ISO C99 7.20.2.2 The srand function).

// RAND_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

Тот факт, что next является статической переменной в верхней части файла, означает, что он невидим для всего, что находится за пределами файла, но видимо для всего внутри (вроде локализованного глобального). Это метод связи между srand() и rand().

Ответ 3

Вы не видите ссылку, потому что (к счастью!) тот, кто проектировал rand(), решил сохранить эту деталь реализации так же, как вы не видите, что внутри FILE от stdio; недостатком является то, что они решили сделать это состояние глобальной (но скрытой) переменной, а не параметром для генератора.

Контрастируйте это с устаревшим rand_r(): это целое число без знака (предполагается, что оно = 32 бит), что означает, что даже он запрещен использовать любой лучший генератор, состояние которого больше чем это, просто потому, что нет места для его хранения!

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

Paxdiablo показал вам пример из стандарта C; см., например, http://en.wikipedia.org/wiki/Multiply-with-carry для примера, используя другой генератор, который вы могли бы скрывать за rand/srand.

Просто для того, чтобы быть экстра-лишним: если бы rand_r был правильно спроектирован, был бы непрозрачный тип, скажем rand_t (который мог бы быть целым числом, структурой, массивом,...), который вы перейдет к rand_r и к некоторому гипотетическому srand_r, как в

rand_t state;
srand_r(&state, 1);
n = rand_r(&state);

Функция rand точно такая же, за исключением того, что существует только одна переменная state.

Ответ 4

rand дает псевдослучайную последовательность чисел.

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

srand для каждого вызова задает указатель на какое-то место в списке, в который вы попадаете. Если вы не вызываете его при каждой попытке или не даете ему исправить семя, это даст вам такой же последовательности. Так много предлагают дать текущую секунду как семя. Но если вы попытаетесь запустить код за одну секунду дважды, он даст вам такую ​​же последовательность.

Для каждого другого начального значения, используемого при вызове srand, можно ожидать, что генератор псевдослучайных чисел будет генерировать другую последовательность результатов при последующих вызовах rand для дальнейшего объяснения