Сгенерировать ту же последовательность случайных чисел в C ++ из заданного начального числа

Я использую mt19937 для генерации случайной строки из заданного семени, например:

std::string StringUtils::randstring(size_t length, uint64_t seed) {
    static auto& chrs = "abcdefghijklmnopqrstuvwxyz";

    thread_local static std::mt19937 rg(seed);
    thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);

    std::string s;
    s.reserve(length);

    while(length--) {
        s += chrs[pick(rg)];
    }

    return s;
}

Я хочу гарантировать, что последовательность случайных чисел (и, следовательно, сгенерированная случайная строка) одинакова на разных машинах одной и той же архитектуры, что должно быть в соответствии с ответы на этот вопрос.

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

Как сгенерировать гарантированную последовательность случайных чисел из заданного начального числа в разных двоичных файлах на одной и той же машинной архитектуре + образе (x86_64 Linux)?


person jeffreyveon    schedule 23.06.2020    source источник
comment
Вы хотите сказать, что генератор возвращает разные числа на ваших платформах?   -  person Bathsheba    schedule 23.06.2020
comment
В одном и том же двоичном файле последовательность одинакова на обеих машинах A и B. Но когда я перестраиваю двоичный файл и обновляю его на машине A, последовательность, сгенерированная A и B, различается.   -  person jeffreyveon    schedule 23.06.2020
comment
Я знаю, о чем вы сейчас говорите. Вы слишком много требуете от генератора. Для MT требуется 19937 бит состояния, а исходное значение, которое вы предоставляете, дает только 64 бита. Есть много вещей о том, как правильно засеять MT19937 - боюсь, ответ выходит за рамки моей зарплаты.   -  person Bathsheba    schedule 23.06.2020
comment
Здесь есть кое-что полезное. Хотя некоторые из одобренных ответов ужасны: stackoverflow.com/questions/45069219/   -  person Bathsheba    schedule 23.06.2020


Ответы (1)


Если вам важны воспроизводимые случайные числа, вам следует избегать дистрибутивов C ++, включая uniform_int_distribution, и вместо этого полагаться на свой собственный способ преобразования случайных чисел из mt19937 в числа, которые вы хотите. (Например, я даю способы сделать это для однородных целых чисел. Обратите внимание, что существуют другие моменты, которые следует учитывать, когда воспроизводимость важна.)

Классы распределения C ++, такие как uniform_int_distribution, не имеют стандартной реализации. В результате эти классы распределения могут быть реализованы по-разному в разных реализациях стандартной библиотеки C ++. Обратите внимание, что не компилятор, операционная система или архитектура решают, какой алгоритм использовать. См. Также этот вопрос.

С другой стороны, случайные движки, такие как mt19937, действительно имеют гарантированную реализацию; они будут возвращать одни и те же случайные числа для одного и того же начального числа во всех совместимых реализациях библиотеки C ++ (в том числе для разных архитектур).

person Peter O.    schedule 23.06.2020