Несколько состояний генератора случайных чисел в c / Unix - PullRequest
3 голосов
/ 30 июня 2009

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

R1 = new_rng(5); //5 is the seed
R2 = new rng(5); //5 is the seed here, too.
a = R1.random();
b = R1.random();
d = R2.random(); //a == d
s1 = R2.get_state(); //save the state of R2
e = R2.random(); //b == e
R2.set_state(s1); //restore the state of R2
f = R2.random(); //b == f

Как мне это сделать? Иногда RNG будут разделяться на разные потоки, и мне нужно будет копировать состояние RNG и при создании нового потока.

Ответы [ 5 ]

6 голосов
/ 30 июня 2009

Используйте erand48() / nrand48() / jrand48() для генерации случайных чисел с плавающей запятой двойной точности, неотрицательных длинных целых или длинных целых чисел со знаком соответственно. Эти функции позволяют вам иметь столько независимых последовательностей, сколько необходимо; состояние передается в качестве аргумента и может быть легко сохранено и восстановлено. Кроме того, последовательность определяется стандартом и не будет изменяться при разных запусках, даже на разных платформах.

Некоторые другие ответы предполагают rand_r(). Эта функция устарела в POSIX.1-2008, которая содержит следующее примечание:

Функция drand48() обеспечивает гораздо более сложный генератор случайных чисел.

Ограничения количества состояний, которые могут переноситься между одним вызовом функции и другим, означают, что функция rand_r() никогда не может быть реализована таким образом, который удовлетворяет всем требованиям к генератору псевдослучайных чисел. Поэтому следует избегать этой функции всякий раз, когда должны выполняться нетривиальные требования (включая безопасность).

Функция rand_r() может быть удалена в следующей версии.

1 голос
/ 30 июня 2009

Используйте rand_r(unsigned *seed) вместо srand() и rand(). Таким образом, вы можете поддерживать несколько случайных семян.

1 голос
/ 30 июня 2009

Прочитайте эту статью о Мерсене Твистере . В самом низу есть ссылки на несколько реализаций. (Другими словами, внедрите PRNG самостоятельно.)

1 голос
/ 30 июня 2009

имеется несколько расширений библиотеки C для различных версий UNIX:

  • BSD как случайный, проверьте состояние initstate / setstate
  • _r вариантов (random_r, srandom_r, initstate_r и т. Д.)
  • rand_r (stdlib.h)

какой вариант поддерживается вашей целевой UNIX?

0 голосов
/ 30 июня 2009

Я не уверен, что вы можете рассчитывать на то, что ваш PRNG произведет точно такую ​​же последовательность, если на самом деле будет идентичное начальное число. Я знаю, что некоторые методы работают таким образом, но я считаю, что некоторые из лучших включают определенную степень недетерминизма, так что идентичное семя может привести к другой последовательности. Вам придется просмотреть документацию по libc с помощью зубчатого гребня и посмотреть, упоминается ли это где-нибудь. Если нет, проверьте код (если вам так повезло иметь доступ к коду).

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

...