Как я могу сохранить состояние генератора псевдослучайных чисел в Perl?

Есть ли способ сохранить текущее состояние встроенного генератора псевдослучайных чисел в Perl, чтобы при повторном запуске моей программы она могла выбрать последовательность с того места, где остановилась, а не начинать с новой последовательности?

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

sub consume_upto_n {
    my ($seed, $n) = @_;
    $n = 1 unless defined $n and $n >= 1;
    srand $seed;
    rand for 1 .. $n - 1;
    return;
}

Например:

srand 0x18;
my @v = map { rand } 1 .. 5;

Потом:

consume_upto_n(0x18, 3);
my @z = map { rand } 3 .. 5;

Затем $z[0] == $v[2], $z[1] == $v[3] и т. д.


person Sinan Ünür    schedule 02.03.2010    source источник


Ответы (2)


Я не думаю, что встроенный rand позволяет вам это сделать. Но вы можете использовать замену rand. Например, Math::Random::MT::Auto позволяет вам сериализовать свои объекты ( предположительно включая $MRMA::PRNG, который является объектом, который используется его заменой rand).

Хотя я не совсем уверен, в чем смысл. Если это достаточно случайная последовательность, как узнать, продолжаете ли вы эту последовательность или начинаете новую?

person cjm    schedule 02.03.2010
comment
@cjm Это для моделирования. Скажем, у меня есть симуляция, требующая 10 000 розыгрышей. Качество генератора случайных чисел не имеет большого значения, но важна способность воспроизводить (для любой заданной комбинации perl + ОС + версия приложения) заданную последовательность. Я хочу иметь возможность прервать его в середине и продолжить с того места, где мы остановились. Таким образом, я могу позже воспроизвести точную последовательность событий, просто сохранив начальное семя. - person Sinan Ünür; 02.03.2010
comment
Синан: Есть несколько вещей, о которых вы просите: возможность продолжить последовательность в какой-то произвольной точке и возможность перезапустить ту же самую точку. И то, и другое можно сделать с помощью одного из модулей Math::Random::*, но, судя по беглому просмотру исходников Perl, это невозможно (легко) сделать с помощью встроенной функции rand() даже из XS! (Perl может вызывать функцию rand() библиотеки c как часть своей функции rand(), и реализация, похоже, зависит от платформы.) - person tsee; 02.03.2010
comment
@cjm и @tsee В любом случае лучше не полагаться на встроенный rand. - person Sinan Ünür; 02.03.2010

Начиная с perl 5.13.4, srand возвращает начальное значение:

srand() теперь возвращает семя

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

person Sinan Ünür    schedule 04.10.2010