Генерация случайных чисел на основе начального значения

Может кто-нибудь объяснить мне, что такое ценность семян? Например, у меня есть этот код:

int MIN=0;
int MAX=100;

srand((unsigned) time(NULL));

srand(2020);

int num = (int)(rand() / (RAND_MAX + 1.0 + MIN) * MAX);

Мне необходимо использовать начальное значение 2020 для генерации чисел от 0 до 100. Я проверял везде, но похоже, что нет учебника, который объясняет, что такое начальное значение и как код должен отличаться от начального значения по умолчанию. Строка 3 моего кода предполагает начальное значение по умолчанию, поэтому оно не работает с начальным значением 2020. Кроме того, MAX равно 100, а MIN равно 0.

Заранее спасибо!


person Hidaisyen    schedule 12.12.2020    source источник
comment
В стандарте ничего не говорится о том, как следует реализовать rand(), но обычно это одно из следующих: en.wikipedia.org/ wiki / Linear_congruential_generator   -  person Shawn    schedule 12.12.2020
comment
правильно разместите свой код   -  person 0___________    schedule 12.12.2020
comment
en.wikipedia.org/wiki/Random_seed   -  person 0___________    schedule 12.12.2020
comment
Если вы вообще не вызываете srand(), тогда используется начальное число по умолчанию (что бы оно ни было) и rand(), вероятно, производит ту же последовательность. Если вы вызываете srand(2020), то это начальное число используется каждый раз при запуске программы, и снова создается та же последовательность, но отличная от первой. Если вы вызываете srand(time(NULL)), PRNG заполняется текущим временем в секундах, поэтому вы получаете другую последовательность при каждом запуске программы (если отмечена одна секунда).   -  person Weather Vane    schedule 12.12.2020
comment
Помимо проблем с семенами, rand() / (RAND_MAX + 1.0 + MIN) * MAX - неправильный способ масштабирования диапазона. Для простого назначения класса вы можете использовать rand() % (MAX-MIN+1) + MIN, предполагая, что вы хотите включить как MAX, так и MIN. Это имеет некоторые недостатки, когда rand низкого качества, но это терпимо для школьных занятий.   -  person Eric Postpischil    schedule 12.12.2020
comment
Этот ответ на другой вопрос не относится к C или rand/srand, но концептуально объясняет, как работают генераторы псевдослучайных чисел. В случае реализации rand на основе lcg, упоминаются функции f() и h(): f(seed) == seed и h(state) == state.   -  person pjs    schedule 12.12.2020
comment
@EricPostpischil Использование арифметики по модулю для создания диапазона подвержено смещению по модулю, что не рекомендуется.   -  person pjs    schedule 12.12.2020
comment
@pjs: В моем комментарии говорится, что в нем есть некоторые недостатки, но он допустим для учебы. Это на этом уровне.   -  person Eric Postpischil    schedule 12.12.2020
comment
@EricPostpischil Я не большой поклонник учить студентов делать что-то неправильно.   -  person pjs    schedule 12.12.2020
comment
@pjs: Я тоже, но обучать лучшему методу слишком сложно, чтобы комментировать в этой ситуации. Их существующий код был в высшей степени неправильным, поэтому было предложено быстрое исправление. Если вы хотите предложить лучшее решение, дерзайте.   -  person Eric Postpischil    schedule 12.12.2020


Ответы (5)


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

http://www.cplusplus.com/reference/cstdlib/srand/

Затем вызов rand () вернет псевдослучайное число в диапазоне от 0 до RAND_MAX.

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

person 0RR    schedule 12.12.2020

У семени есть 2 использования. Самый распространенный - запуск случайного генератора с другим значением. Это имеет значение, когда вы хотите получить случайное значение для криптоалгоритма. Когда вы запускаете программу, вы не хотите использовать одно и то же значение при каждом запуске ...

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

person Serge Ballesta    schedule 12.12.2020

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

В C srand и rand нельзя использовать для создания воспроизводимой последовательности псевдослучайных чисел, потому что стандарт, определяющий язык C, не указывает, что это за последовательность, даже если задано начальное число . Примечательно, что rand использует неопределенный алгоритм случайных чисел, и этот алгоритм может отличаться в разных реализациях C, включая версии той же стандартной библиотеки. Не компилятор, система или архитектура решают, какая реализация rand и srand будет использоваться. См. Также эти вопросы:

person Peter O.    schedule 12.12.2020

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

Итак, вы вызываете srand, чтобы установить начальную точку последовательности для rand. Значение, которое вы передаете srand, - это любое значение unsigned int. В стандарте C для значения нет определенного значения. Вы просто даете srand число, например 1, чтобы получить одну последовательность, 2, чтобы получить другую последовательность, 3, чтобы получить другую последовательность, и так далее. У вас нет другого контроля над фактическими генерируемыми значениями; установка для начального числа определенного значения не гарантирует, что первый вызов rand вернет какое-либо конкретное задокументированное значение.

Стандарт C также не определяет какой-либо метод вычисления чисел в последовательности. Каждая реализация C может выбрать свой собственный метод. В некоторых реализациях C используются плохие методы, в которых числа совсем не случайны, а некоторые закономерности легко заметить. (По этой причине часто рекомендуется использовать альтернативы, такие как srandom и random Unix.)

Когда программа отлаживается или используется в качестве присвоения класса, обычно вызывается srand с фиксированным значением, например srand(2020). В результате rand каждый раз генерирует одни и те же числа. Это упрощает отладку программы или проверку результатов студенческих программ. Когда создаются различные последовательности номеров, обычно srand называют srand(time(NULL)). Предполагая, что время доступно (time(NULL) может вернуть -1 в случае ошибки), это заставляет программу использовать разные последовательности в разное время. (Обычно значение time как целое число изменяется раз в секунду, но это может варьироваться в зависимости от реализации C.)

person Eric Postpischil    schedule 12.12.2020

Чтобы сгенерировать случайное число с определенным начальным числом, используйте srand, чтобы установить начальное число только для однократного использования.
Затем используйте rand, чтобы сгенерировать случайное число. Диапазон по умолчанию составляет от 0 до RAND_MAX (RAND_MAX = 32767).
Чтобы определить максимальное число, просто переопределите RAND_MAX с помощью операторов прекомпилятора (включая побочные эффекты) или используйте По модулю %.

Переопределить RAND_MAX

#ifdef RAND_MAX
#undef RAND_MAX
#define RAND_MAX 100
#endif

Использовать по модулю

srand(2020);
int random_number = rand() % 100;
person Daniel Schischkin    schedule 12.12.2020
comment
Ссылка: pubs.opengroup.org/onlinepubs/009604499/basedefs/stdlib. h.html - person Daniel Schischkin; 12.12.2020
comment
RAND_MAX определяется реализацией. Вы не должны его менять. - person Weather Vane; 12.12.2020
comment
@WeatherVane он всегда может перекомпилировать стандартную библиотеку :) чтобы сделать свою реализацию :) - person 0___________; 12.12.2020
comment
@P__JsupportswomeninPoland абсолютно. Это будет новое дополнение. - person Weather Vane; 12.12.2020