rand () семя, которое не требует времени?

Использование srand(time(NULL)) кажется чрезмерно детерминированным. Например, когда я запускаю std::cout << rand() % 9000, я получаю 4275. Когда я запускаю его снова, я получаю 4311. Это тоже зависит от времени.


person Coffee Maker    schedule 02.06.2014    source источник
comment
Это было случайно, что они оказались так близко друг к другу. Это случается, когда ваш номер случайный.   -  person Martin Konecny    schedule 02.06.2014
comment
Кроме того, поскольку вы просили C ++, вы можете рассмотреть возможность использования новой библиотеки случайных чисел < / а>.   -  person Csq    schedule 02.06.2014
comment
Хотя ваш пример не является достаточным доказательством проблемы, я бы не стал использовать rand. Если вы используете ГПСЧ, который не отстой, он будет выводить совершенно разные последовательности, даже если входные данные очень похожи. Даже с идеальными семенами rand имеет ужасные недостатки, включая недостаточный размер семян и размер.   -  person CodesInChaos    schedule 02.06.2014
comment
@Csq, удивительно, сколько ответов на этот вопрос не пытается ответить на настоящий вопрос. Я думаю, что этот достаточно конкретный, чтобы его можно было считать другим.   -  person Mark Ransom    schedule 02.06.2014
comment
Вы думаете, что это детерминировано? Я призываю вас угадать следующий номер.   -  person abelenky    schedule 02.06.2014
comment
@MarkRansom, удивительно, сколько ответов на этот вопрос не пытаются ответить на сам вопрос - да. Хотя мне нравится srand((time.tv_sec * 1000) + (time.tv_usec / 1000)) в принятом ответе.   -  person Csq    schedule 02.06.2014
comment
@MartinKonecny, это не случайно, я сам столкнулся с той же проблемой с реализацией Microsoft rand. Используемая формула показывает определенную корреляцию между семенами и первым произведенным значением.   -  person Mark Ransom    schedule 02.06.2014
comment
Для генерации самого начального значения с высокой энтропией лучше всего использовать std::random_device как часть новой библиотеки <random>. Для старых компиляторов (до C ++ 11) вы можете использовать случайную библиотеку TR1 или Boost.Random, которые почти одинаковы. В противном случае вы также можете читать из /dev/random или /dev/urandom или их эквивалента, отличного от Unix (?).   -  person Mikael Persson    schedule 02.06.2014


Ответы (3)


Если вы используете C ++, я бы рекомендовал использовать <random> из стандартной библиотеки. Это намного надежнее, чем rand()

person vsoftco    schedule 02.06.2014
comment
+1 А если вы используете более старый компилятор, <random> был добавлен как часть TR1, поэтому он также доступен в <tr1/random> как std::tr1::mt19937 и т. Д. - person Praetorian; 02.06.2014

Проблема с вашим подходом заключается в том, что вы просто берете две выборки и предполагаете, что они репрезентативны для всей генеральной совокупности (то есть: статистическая ошибка, основанная на незначительном размере выборки). Функция rand() возвращает значения, которые эффективно образуют равномерное распределение на [0, RAND_MAX]. Приведенный вами пример не очень удачный.

Во-вторых, вызов srand(time(NULL)) - это неплохой подход на большинстве современных машин. Единственный раз, когда это представляет значительную угрозу безопасности, - это работа на одноядерном встроенном чипе, у которого нет резервного аккумулятора для системных часов. Я работал с некоторыми платами Motorola, которые делают это, и примерно в 90% случаев, когда наша программа загружалась, мы получали такое же случайное начальное значение. Я считаю, что некоторые машины Бинго в 80-х были уязвимы для этого, поскольку они были разработаны для работы круглосуточно, без выходных, но операторы выключали их каждую ночь.

Наконец, rand() в лучшем случае наполовину приличен. Если вам нужен генератор случайных чисел с лучшими свойствами (то есть: «близкие» начальные значения, не обеспечивающие аналогичный шаблон, более широкий диапазон выходных значений, минимальное смещение), рассмотрите возможность использования внешнего алгоритма ГСЧ.

Ссылки


  1. Рекомендуемый способ инициализации srand?, дата обращения 02.06.2014, <https://stackoverflow.com/questions/322938/recommended-way-to-initialize-srand>
  2. Какая разница между функциями rand () и random ()?, дата обращения 02.06.2014, _ 6_
  3. Какие существуют альтернативы функциям rand () и srand () библиотеки C?, дата обращения 02.06.2014, _ 7_
person Cloud    schedule 02.06.2014

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

  srand(time(NULL));
  rand();
  rand();

Вы также можете заполнить его, используя значение из /dev/random или /dev/urandom (или Windows эквивалент.

person Mark Ransom    schedule 02.06.2014