使用boost :: random跨平台的一致随机数生成器

时间:2014-10-22 11:36:57

标签: c++ boost random boost-random

我们一直在我们的项目中使用boost :: random。最近,一个失败的测试单元让我对其中一个属性产生了兴趣:不同版本的Boost生成的数字序列可能会有所不同,具体取决于使用的分布。

此行为似乎在所有发行版中都不一致。大多数情况下,使用具有相同种子的RNG的均匀分布产生相同的结果。其他分布(例如normallognormalbinomialdiscrete可能会显示这些差异。

我已经整理了一个显示问题的简单C ++程序:

#include <iostream>
#include <boost/random.hpp>
#include <stdint.h>

void uniform() {
  uint32_t seed = 42;
  boost::mt19937 rng(seed);
  boost::random::uniform_real_distribution<double> distro(0., 1.);
  std::cout << "uniform" << std::endl;
  for (int i=0; i<10; ++i) {
    std::cout << distro(rng) << std::endl;
  }
}

void normal() {
  uint32_t seed = 42;
  boost::mt19937 rng(seed);
  boost::random::normal_distribution<double> distro(0., 1.);
  std::cout << "normal" << std::endl;
  for (int i=0; i<10; ++i) {
    std::cout << distro(rng) << std::endl;
  }
}

void discrete() {
  uint32_t seed = 42;
  boost::mt19937 rng(seed);
  std::vector<double> P;
  P.push_back(0.3);
  P.push_back(0.4);
  P.push_back(0.3);
  boost::random::discrete_distribution<uint64_t> distro(P.begin(), P.end());
  std::cout << "discrete" << std::endl;
  for (int i=0; i<10; ++i) {
    std::cout << distro(rng) << std::endl;
  }
}

int main() {
  uniform();
  normal();
  discrete();
}

这个简单的程序将显示Boost 1.56(在OSX上运行)的不同数字序列:

uniform
0.37454
0.796543
0.950714
0.183435
0.731994
0.779691
0.598658
0.59685
0.156019
0.445833
normal
-0.638714
-0.836808
-0.400566
-0.869232
-0.972045
-0.758932
-1.30435
1.22996
0.249399
0.286848
discrete
1
2
2
1
0
0
0
2
1
2

或者使用Boost 1.50(在Ubuntu 12.10上运行):

uniform
0.37454
0.796543
0.950714
0.183435
0.731994
0.779691
0.598658
0.59685
0.156019
0.445833
normal
-1.25821
1.2655
0.606347
-0.19401
-0.196366
-1.72826
-1.09713
-0.783069
0.604964
0.90255
discrete
2
1
2
1
1
0
1
1
0
1

请注意,均匀分布按预期工作:即,相同的种子在两个版本上生成一致的数字序列。正态和离散分布的行为不一样。

有没有办法“修复”这个?即有不同的平台生成完全相同的序列独立于升级版本?

1 个答案:

答案 0 :(得分:1)

似乎boost :: random并不能保证你为不同版本的某些种子获得相同的数字序列。

E.g。在版本1.56中,他们更改了算法以生成从Box-Muller方法到Ziggurat方法的正态分布随机数:

https://github.com/boostorg/random/commit/f0ec97ba36c05ef00f2d29dcf66094e3f4abdcde

此方法速度更快,但也会生成不同的数字序列。

可能已对其他发行版进行了类似的更改。均匀分布仍然产生与默认情况下基本rng(即mersenne twister 19937)的输出相同的结果。