Почему у меня всегда получается одна и та же последовательность случайных чисел с rand()?

Это первый случай, когда я пытаюсь использовать случайные числа с C (я пропускаю С#). Вот мой код:

int i, j = 0;
for(i = 0; i <= 10; i++) {
    j = rand();
    printf("j = %d\n", j);
}

с этим кодом, я получаю одну и ту же последовательность каждый раз, когда запускаю код. Но он генерирует различные случайные последовательности, если я добавляю srand(/*somevalue/*) до цикла for. Может кто-нибудь объяснить, почему?

Ответ 1

Вы должны засеять его. Посадить его со временем - хорошая идея:

srand()

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

int main ()
{
  srand ( time(NULL) );
  printf ("Random Number: %d\n", rand() %100);
  return 0;
}

Вы получаете одну и ту же последовательность, потому что rand() автоматически высевается со значением 1, если вы не вызываете srand().

Изменить

Из-за комментариев

rand() вернет число от 0 до RAND_MAX (определенное в стандартной библиотеке). Использование оператора modulo (%) дает остаток от деления rand()/100. Это заставит случайное число находиться в диапазоне 0-99. Например, чтобы получить случайное число в диапазоне от 0 до 999, мы применили бы rand()%1000.

Ответ 2

rand() возвращает псевдослучайные номера. Он генерирует числа, основанные на заданном алгоритме. Начальная точка этого алгоритма всегда одна и та же, поэтому вы увидите ту же последовательность, сгенерированную для каждого вызова. Это удобно, когда вам нужно проверить поведение и последовательность вашей программы.

Вы можете установить "семя" случайного генератора с помощью функции srand (только вызов srand один раз в программе). Один из распространенных способов получения разных последовательностей из генератора rand() состоит в том, чтобы установить семя на текущее время или id процесса:

srand (время (NULL)); или srand (getpid()); в начале программы.

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

Ответ 3

Для цитаты из man rand:

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

Если начальное значение не указано, Функция rand() автоматически посеяно со значением 1.

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

Ответ 4

Если я помню цитату из оригинальной работы Кнута "Искусство компьютерного программирования" в начале главы о генерации случайных чисел, она выглядит примерно так:

"Любой, кто пытается генерировать случайные числа математическими средствами, технически говоря в состоянии греха".

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

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

Поистине генераторы случайных данных имеют тенденцию смотреть на внешние источники. Радиоактивный распад является фаворитом, как и поведение квазаров. Все, чьи корни находятся в квантовых эффектах, является фактически случайным - во многом до раздражения Эйнштейна.

Ответ 5

Здесь много ответов, но никто, кажется, действительно не объяснил, почему именно rand() всегда генерирует одну и ту же последовательность с тем же самым семенем или даже то, что действительно делает семя. Так вот.

Функция rand() поддерживает внутреннее состояние. Понятно, что это можно рассматривать как глобальную переменную некоторого типа rand_state. Каждый раз, когда вы вызываете rand(), он выполняет две вещи. Он использует существующее состояние для вычисления нового состояния и использует новое состояние для вычисления числа, возвращаемого вам:

state_t rand_state = INITIAL_STATE;

state_t calculate_next_state(state_t s);
int calculate_return_value(state_t s);

int rand(void)
{
    rand_state = calculate_next_state(rand_state);
    return calculate_return_value(rand_state);
}

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

Теперь здесь, где входит srand(). Он позволяет перейти к другой точке пути:

state_t generate_random_state(unsigned int seed);

void srand(unsigned int seed)
{
    rand_state = generate_random_state(seed);
}

Точные детали state_t, calculate_next_state(), calculate_return_value() и generate_random_state() могут варьироваться от платформы к платформе, но обычно они довольно просты.

Вы можете видеть из этого, что каждый раз, когда запускается ваша программа, rand_state собирается начать с INITIAL_STATE (что эквивалентно generate_random_state (1)) - вот почему вы всегда получаете одну и ту же последовательность, если вы не используете srand().

Ответ 6

Генераторы случайных чисел на самом деле не являются случайными, они, как и большинство программ, полностью предсказуемы. То, что делает rand, создает различное псевдослучайное число каждый раз, когда оно называется One, которое кажется случайным. Чтобы правильно использовать его, вам нужно дать ему другую отправную точку.

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

int main ()
{
  /* initialize random seed: */
  srand ( time(NULL) );

  printf("random number %d\n",rand());
  printf("random number %d\n",rand());
  printf("random number %d\n",rand());
  printf("random number %d\n",rand());

  return 0;
}

Ответ 7

Это от http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#rand:

Декларация:

void srand(unsigned int seed); 

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

Ответ 8

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

Если вы хотите что-то случайное каждый раз, вы можете попробовать:

srand (time (0));

Ответ 9

вызовите srand(sameSeed) перед вызовом rand(). Подробнее здесь.

Ответ 10

Посещение rand()

void srand (unsigned int seed)

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

Чтобы создать различную псевдослучайную последовательность при каждом запуске вашей программы, сделайте srand (time (0))

Ответ 11

Никто из вас, ребята, не отвечает на его вопрос.

с этим кодом я получаю одну и ту же последовательность каждый раз в коде, но он генерирует случайные последовательности, если я добавляю srand (/somevalue/) перед циклом for. может кто-нибудь объяснить, почему?

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

Ответ 12

Кстати: факт, что rand НЕ случайный (PRNG = PSEUDO Random Number Generator, где псевдо - ключевое слово!), может быть очень полезным.

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

Псевдо-случайный - прекрасная вещь.:)


PS Если вы когда-либо полагаетесь на rand (om), синхронизированный, однако, вы должны закодировать свою собственную реализацию - иначе платформа и другие различия испортят ваше удовольствие.:)