跨平台一致的伪随机数生成器

32

我正在寻找一种方法来生成伪随机数序列,在任何平台上都能产生给定种子的相同序列结果。 我假设 rand() / srand() 不会保持一致(我可能对这个假设有错误)。


2
查看我的问题和回答,了解关于C++11随机生成器的内容。C++11的mt19937生成器可以在所有平台上提供一致的结果,但标准分布却不能,因此我创建了自己的分布:https://dev59.com/T1sW5IYBdhLWcg3wfXb6 - Arno Duvenhage
如果您选择使用线性同余生成器,这个维基百科页面会很有用。特别是您可以使用ISO / IEC 9899中建议的rand的C实现。在我的测试中,当unsigned long使用32(最小值)或64位时,它会给出完全相同的结果。 - Gabriel Devillers
5个回答

19

1
如果您不想使用Boost,可以使用Mersenne Twister的原始实现,该实现是用纯C编写的。近年来,MT组添加了一些额外的端口,可以利用SIMD、OpenCL和CUDA。 - sfstewman
3
请您查看我的有关 C++11 随机数生成器的问题和答案。C++11 中的 mt19937 产生的结果在所有平台上都是一致的,但标准分布却不是,因此我编写了自己的分布函数:https://dev59.com/T1sW5IYBdhLWcg3wfXb6 - Arno Duvenhage

8

Knuth已经将在《计算机程序设计艺术》第3.6节中描述的伪随机数生成器的C(和FORTRAN)源代码发布到公共领域


6
我知道这是一个旧的帖子,但是现在有许多新的选项可用于C++11。以下是来自该页面的一个简化示例,默认情况下使用Mersenne Twister引擎和正态分布:
Mersenne Twister引擎和Normal分布:new options available
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::round(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

8
按照C++11标准指定的分布,即使使用相同的代码和种子,也不保证能够产生可再现的结果。更别说使用不同的库,比如libc++和libstdc++了。 - OmnipotentEntity
2
查看我的问题和答案,了解C++11随机生成器。C++11的mt19937在所有平台上都提供一致的结果,但标准分布不是这样,因此我创建了自己的分布:https://dev59.com/T1sW5IYBdhLWcg3wfXb6 - Arno Duvenhage

1
我一直在为此开发一个名为 simplerandom 的库。它应该是跨平台的,我也打算针对多种语言进行目标设置。目前它支持 C 和 Python(两种语言生成相同的数字)。我计划很快在 C++ 中实现相同的生成器,遵循 Boost 和 C++11 随机 API。

0

快速搜索参考资料得出:

使用相同种子的两个不同初始化,指示伪随机生成器在两种情况下对后续调用rand生成相同的结果序列。

但问题仍然存在。我假设上述规范仅适用于同一进程中的RNG。它很可能没有指定任何关于跨平台或跨编译器的事情。您最好的选择可能是找到一个可用于所有所需平台的库。然后,如果使用相同的值进行种植,它们应该返回相同的数字序列。


我认为这指的是任何特定实现rand()的行为,并不提供任何跨编译器或跨平台的保证。此外,使用内置PRNG会冒着各种不必要的风险。使用一个已知适合您需求的PRNG库。 - dmckee --- ex-moderator kitten

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