Как часто следует вызывать srand() в приложении C++?

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


person laurent    schedule 05.08.2011    source источник
comment
srand не делает rand более случайным. Это никоим образом не гарантирует разумной случайности. Он просто заставляет последовательность случайных чисел начинаться с указанной точки.   -  person jalf    schedule 05.08.2011
comment
@jalf Я удивлен, что за более чем 8 лет после того, как был сделан этот комментарий, он не был оспорен. Утверждение, что последовательность случайных чисел начинается с указанной точки, кажется, противоречит cplusplus.com: для каждого другого начального значения, используемого в вызове srand, можно ожидать, что генератор псевдослучайных чисел будет генерировать другую последовательность. результатов в последующих вызовах rand.   -  person Theo d'Or    schedule 16.01.2020
comment
@Theod'Or, и комментарий jalf, и ваша цитата из cplusplus говорят об одном и том же. Какая разница?   -  person laurent    schedule 16.01.2020
comment
@laurent Разница заключается в том, что вы начинаете с указанной точки, а не в другой последовательности результатов. Первый предполагает, что диапазон сгенерированных чисел всегда будет одинаковым, независимо от того, какое начальное число, второе предлагает разные числа для разных начальных чисел. Я предполагаю, что ваше прочтение последнего состоит в том, что оно также может быть истолковано как просто другая отправная точка в неизменной последовательности. Но в этом случае утверждение cplusplus верно только до конца периода генерации.   -  person Theo d'Or    schedule 16.01.2020
comment
На самом деле Википедия утверждает, что rand() является линейным конгруэнтным генератором, и, как их иллюстрация показывает, что новое начальное число, если оно не совпадает с числом, которое генератор выдал бы с предыдущим начальным числом, приведет к другой последовательности чисел. Однако, если семя совпадает, меняется только начальная точка.   -  person Theo d'Or    schedule 19.01.2020
comment
За исключением того, что я только что провел тест и не получил другую начальную точку с начальным числом, соответствующим предыдущему выводу, а другую последовательность. Я подозреваю, что статья в Википедии устарела и rand() больше не является простым линейным конгруэнтным генератором.   -  person Theo d'Or    schedule 19.01.2020


Ответы (4)


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

person Kerrek SB    schedule 05.08.2011
comment
Boost::random более переносим, ​​чем drand48_r, или используйте C++0x random (который является производным от Boost) - person MSalters; 05.08.2011
comment
@MSalters: Конечно, я бы в любой день воспользовался новыми функциями <random>. Их просто немного сложнее настроить, поэтому я подумал, что отвечаю в духе вопроса - но на самом деле, используйте <random>, если можете! - person Kerrek SB; 05.08.2011
comment
Спасибо за этот очень полный ответ. - person laurent; 06.08.2011
comment
Если вы часто выполняете повторное заполнение, вы можете нарушить некоторые статистические свойства случайных чисел. Некоторые доказательства, подтверждающие это утверждение, были бы очень кстати. - person Theo d'Or; 16.01.2020
comment
@Theod'Or: По упущению: ГСЧ обычно не дают гарантий относительно своего начального значения относительно начального числа, а только в отношении статистики развертывания, начинающегося с (любого) одного фиксированного начального числа. - person Kerrek SB; 26.01.2020

Только один раз, в начале вашего приложения.

person Dr McKay    schedule 05.08.2011

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

person Paul Carroll    schedule 05.08.2011

вызовите его один раз, когда приложение запустится

person cprogrammer    schedule 05.08.2011