使用给定的种子在C++中生成相同的随机数序列。

4

我正在使用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)?


你是说在你的平台上生成器返回不同的数字? - Bathsheba
在相同的二进制文件上,机器A和B生成的序列是相同的。但是当我重新构建二进制文件并将其更新到机器A上时,由A和B生成的序列是不同的。 - jeffreyveon
2
我现在知道你在说什么了。你对生成器的要求太高了。MT需要19937位的“状态”,而你提供的种子只有其中的64位。关于如何正确地为MT19937提供种子,有很多相关资料 - 不过恐怕这已经超出了我的能力范围。 - Bathsheba
这里有一些有用的东西。尽管一些得到赞同的答案很糟糕:https://dev59.com/ZVcO5IYBdhLWcg3w7lgm - Bathsheba
1个回答

4
如果你关心可重复的“随机”数,你应该避免使用C++分布类,包括uniform_int_distribution,而是依赖于你自己的方式将伪随机数从mt19937转换为你想要的数字。(例如,我给出了一些方法来处理均匀整数。注意,在关注可重复性时还有其他要考虑的事情。)
C++分布类(如uniform_int_distribution没有标准实现。因此,在不同的C++标准库实现中,这些分布类可以以不同的方式实现。请注意,决定使用哪个算法的不是“编译器”,“操作系统”或“架构”。另请参见此问题
另一方面,像mt19937这样的随机引擎确实具有保证的实现;在所有符合C++库实现(包括不同的“架构”)的情况下,它们将返回相同的伪随机数种子。例外情况是default_random_engine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接