跨平台一致的伪随机数

Posted

技术标签:

【中文标题】跨平台一致的伪随机数【英文标题】:Consistent pseudo-random numbers across platforms 【发布时间】:2010-10-29 16:07:14 【问题描述】:

我正在寻找一种生成伪随机数序列的方法,该方法将在任何平台上为给定种子产生相同的序列结果。我假设 rand() / srand() 不会保持一致(我很容易对这个假设出错)。

【问题讨论】:

查看我对 C++11 随机生成器的问答。 C++11 mt19937 在所有平台上提供一致的结果,但标准发行版没有,所以我创建了自己的发行版:***.com/questions/34903356/… 如果您选择使用线性同余生成器,this wikipedia page 很有用。特别是,您可以使用 ISO/IEC 9899 中建议的 rand 的 C 实现。在我的测试中,当 unsigned long 使用 32(最小值)或 64 位时,它给出了相同的结果。 【参考方案1】:

Mersenne Twister (from Boost.Random) 之类的东西是确定性的。

【讨论】:

如果你不想使用Boost,你可以使用Mersenne Twister的原始实现,它是用纯C编写的。近年来,MT组增加了一些额外的端口,可以使使用 SIMD、OpenCL 和 CUDA。 查看我对 C++11 随机生成器的问答。 C++11 mt19937 在所有平台上提供一致的结果,但标准发行版没有,所以我创建了自己的发行版:***.com/questions/34903356/…【参考方案2】:

Knuth 有released into the public domain C (and FORTRAN) source code 用于计算机编程的艺术第 3.6 节中描述的伪随机数生成器。

【讨论】:

【参考方案3】:

我意识到这是一个旧线程,但现在使用 C++11 有一大堆 new options available。这是页面中的一个提炼示例,默认使用Mersenne Twister 引擎和Normal 分发:

#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';
    

【讨论】:

C++11 标准指定的分布不需要在给定相同种子的情况下产生可重现的结果,即使使用相同的代码也是如此。更不用说使用不同的库了,比如 libc++ vs libstdc++。 查看我对 C++11 随机生成器的问答。 C++11 mt19937 在所有平台上提供一致的结果,但标准发行版没有,所以我创建了自己的发行版:***.com/questions/34903356/…【参考方案4】:

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

【讨论】:

【参考方案5】:

快速搜索到的reference 说:

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

但问题仍然存在。我假设上述规范仅适用于同一流程中的 RNG。它很可能没有指定任何关于跨平台或跨编译器的东西。您最好的选择可能是找到一个可用于所有所需平台的库。那么你应该相当安全,如果用相同的值作为种子,它们会返回相同的数字序列。

【讨论】:

我相信这是指rand() 的任何特定实现的行为,并且不提供任何跨编译器或跨平台保证。此外,使用内置 PRNG,您会冒各种不想要的属性的风险。使用已知适合您需求的 PRNG 库。

以上是关于跨平台一致的伪随机数的主要内容,如果未能解决你的问题,请参考以下文章

固定密度为 1s 的伪随机数生成器

一个简单的伪随机数发生算法(转)

关于SQLite的伪随机数

线性同余法的伪随机数

集合的伪随机遍历

集合的伪随机遍历