Генератор случайных чисел для пакета программ

Поэтому обычно я использую что-то вроде:

srand(time(0));

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

Какова лучшая стратегия для заполнения моего ГСЧ, когда я хочу, чтобы несколько программ запускались одновременно и все получали разные начальные значения?


person pjreddie    schedule 18.04.2014    source источник
comment
Используйте более мелкозернистый таймер (например, системный счетчик наносекунд) и смешайте его с идентификатором процесса. Все еще не будет достаточно хорош для приложений безопасности или моделирования методом Монте-Карло.   -  person Mark Lakata    schedule 18.04.2014
comment
используйте rdtsc stackoverflow.com/a/7617612/995714, это количество псевдоциклов с момента включения процессора. Если вам нужно больше уверенности, выполните xor с помощью PID.   -  person phuclv    schedule 18.04.2014


Ответы (3)


Используйте srand(time(0) ^ getpid()) для перестановки вашего начального числа на значение, специфичное для процесса. Это обеспечит разные начальные значения для процессов, запущенных в течение одной секунды. Будьте осторожны, чтобы не использовать это для чего-либо «важного», например, для криптографии или реальных денег.

Перестановка выполняется с помощью оператора «исключающее ИЛИ» или XOR «^». Поскольку мы знаем, что два одновременно запущенных процесса обязательно должны иметь разные идентификаторы процессов, путем xoring ответа от time(0) с текущим PID мы можем получить некоторую уверенность в том, что два разных процесса не будут иметь точно такое же начальное значение. .

Обратите внимание, что это очень слабая гарантия, так как мы только крутим несколько битов. Если время увеличится ровно на одну секунду, а идентификатор процесса увеличится ровно на единицу, при определенных обстоятельствах вы получите идентичные начальные значения.

Если вам нужны действительно разные начальные числа случайных чисел, тогда вы хотите прочитать 4 байта из /dev/random, а затем использовать это как целое число для заполнения вашего RNG.

И еще раз, ПОЖАЛУЙСТА, не используйте эту случайную последовательность чисел ни для чего "важного". И под важным я подразумеваю что-то большее, чем простая симуляция Монте-Карло или игра в камень-ножницы-бумага.

person caskey    schedule 18.04.2014
comment
Любить это. Возможно, более подробно о том, как работает XOR для создания нового отдельного значения. +1 - person Brian Tracy; 18.04.2014
comment
Если у вас есть подходящая библиотека, вы можете использовать безопасную хеш-функцию, такую ​​как SHA-1, чтобы сделать начальное число ГСЧ из текущего времени и идентификационного номера процесса. Думаю, если RNG действительно хорош, это не должно иметь значения, но меня немного беспокоит, что различные значения PID будут отличаться всего на несколько битов. Защищенные хэш-функции действительно выполняют работу по хэшированию, и даже разница в один бит на входе приведет к большой разнице на выходе. Это может занять слишком много времени для использования для каждого значения ряда ГСЧ, но только для начального числа это, вероятно, должно быть в порядке. - person steveha; 18.04.2014
comment
Даже если вы используете SHA-1 для создания начального числа, у вас не больше энтропии, чем у базовых вызовов time() и getpid(), поэтому делать что-то более сложное — пустая трата усилий. Если OP собирается использовать srand/random, то лучшее, что они могут сделать, — это вытащить свое семя из /dev/random. - person caskey; 18.04.2014
comment
+1 за разумное и несложное решение time(0) ^ getpid()). У него есть некоторые проблемы, так как gid имеет некоторую предсказуемость, и, конечно же, time(0) тоже. Может быть, если бы в каждой программе было задумано и зафиксировано в коде свое случайное значение: time(0) ^ getpid() ^ my_program_mask. Я думаю, в конце концов, каждой программе нужен вызов действительно случайного источника. - person chux - Reinstate Monica; 18.04.2014
comment
Отлично. Для моего использования мне на самом деле просто нужен был getpid(), и я мог бы полностью отказаться от случайного числа (мне просто нужен был бит, который переворачивался туда и обратно), но это гораздо более полный ответ, если кто-нибудь найдет это в будущем. - person pjreddie; 18.04.2014

Возможно, вам нужно использовать getpid(), а также несколько секунд (и, возможно, весь второй раз). Может быть, сделать хэш MD5 значений и использовать его? Использование getpid() гарантирует, что часть данных, которые вы используете, будет уникальной для каждого процесса, но само по себе не дает вам слишком большой случайности в вашем семени. Конечно, вряд ли использование rand() будет хорошим генератором случайных чисел. Вы, конечно, не можете использовать его для криптографии.

person Jonathan Leffler    schedule 18.04.2014

Вы можете комбинировать time(0) с другим значением, специфичным для программы. Например, XOR с приличным хэшем имени программы (обычно достаточно argv[0]) или даже просто (желательно хеш) идентификатора процесса (если они запущены на одном хосте, иначе XOR дальше с хэшем имя хоста или IP). Вы даже можете пойти дальше и использовать хэш UUID.

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

person Tony Delroy    schedule 18.04.2014