代码之家  ›  专栏  ›  技术社区  ›  DanielTuzes

如何使用<random>在多种类型的编译器和内核上生成相同的随机数序列?

  •  20
  • DanielTuzes  · 技术社区  · 11 年前

    问题是

    我需要在不同的机器和编译器上生成相同的(伪)随机数序列。如果我使用相同的内核,似乎在g++中实现mersenne twister(MT)效果很好:无论我在较新的机器上编译程序,使用g++4.9或4.7,我都会得到相同的随机数。但如果我使用较旧的内核或改用Visual Studio的编译器,则会得到不同的结果。没关系,因为没有保证 mersenne_twister_engine::seed 将不同编译器的内部状态设置为相同。

    我已经试过了

    我很难申请 operator<< 在生成器上生成一个唯一的结果,可用于在其他机器上设置生成器 operator>> ,但如果 mt19937 ,它似乎不起作用。说清楚一点,在电脑a上我有密码

    mt19937 generator1A;
    uniform_int_distribution<int> distribution(0, 1000);
    
    cout << "Generating random numbers with seed 1000" << endl;
    
    generator1A.seed(1000);
    generator1A(); //to advance the state by one so operator>> will give a longer output; this is not necessary indeed
    ofstream test("testseed1000.txt");
    test << generator1A << endl;
    
    for (int i = 0; i < 10; ++i)
        cout << distribution(generator1A) << endl;
    

    它产生252590893。。。,和一个长文件。我将文件传输到另一台机器B,并运行以下代码:

    mt19937 generator1B, generator2B;
    uniform_int_distribution<int> distribution(0, 1000);
    
    cout << "Generating random numbers with seed 1000, and with operator>>" << endl;
    generator2B.seed(1000);
    generator2B(); // to advance the state by one here as well
    
    ifstream test("testseed1000.txt");
    
    test >> generator1B;
    cout << "************************" << endl;
    cout << generator1B << endl;
    cout << "************************" << endl;
    cout << "With seed\twith operator>>" << endl;
    
    for (int i = 0; i < 10; ++i)
        cout << distribution(generator2B) << "\t" << distribution(generator1B) << endl;
    

    它产生

    654     205
    205     115
    115     610
    

    问题

    你能给出建议,如何在Windows上至少用VC++,在Debian和Ubuntu上至少用g++生成相同的(伪)随机数吗?如果可能的话,我想使用std,我不想实现我自己的MT引擎。

    笔记:

    • 创建数以百万计的随机数,然后读入并不是解决方案
    • 我必须使用MSVS进行代码开发,使用unix服务器进行模拟
    • 除MT发动机外,其他发动机也受到欢迎,但我更喜欢MT
    2 回复  |  直到 11 年前
        1
  •  13
  •   user1084944 user1084944    11 年前

    要从问题中删除变量,请尝试查看随机数引擎的输出,而不是将其输入到分布中。

    我只是看了几页文档 uniform_int_distribution ,并且它没有给出关于如何使用统一随机数生成器的输出的任何声明。我不知道标准是怎么说的。

    我预测你 从mersenne twister获得相同的输出,但您将这些输出输入到 均匀分布 .

    如果这是真的,那么为了获得相同的随机数序列,您必须使用分布函数的外部实现,以确保在所有系统上获得相同的结果。

        2
  •  10
  •   T.C. Yksisarvinen    11 年前

    该标准要求引擎通过指定默认构造的引擎在第10000次调用时必须生成的值(它还指定了引擎的实际转换和生成算法),在实现中生成可重复的数字。例如,对于 mt19937 标准规定([rand.dedef]/p3):

    typedef mersenne_twister_engine<uint_fast32_t,
           32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253>
           mt19937;
    

    所需的行为 :10000 连续调用类型的默认构造对象 1993年7月 应产生值 4123659995

    对于分配,没有这样的要求;相反,标准规定([rand.dist.general]/p3):

    生成每个指定分布的算法如下 定义了实现。

    换句话说,实现可以使用不同的分发算法,但必须记录它们使用的算法。MSVC和libstdc++可能使用不同的算法。

    如果您想要完全的可移植性,可以考虑使用外部实现,例如Boost.Random的发行类。