为什么GCC和MSVC std :: normal_distribution不同?

时间:2016-07-22 18:14:26

标签: c++ visual-studio c++11 gcc visual-c++

我有一个简单的代码示例:

#include <iostream>
#include <random>
using namespace std;
int main() {
    minstd_rand0 gen(1);
    uniform_real_distribution<double> dist(0.0, 1.0);
    for(int i = 0; i < 10; ++i) {
        cout << "1 " << dist(gen) << endl;
    }

    normal_distribution<double> dist2(0.0, 1.0);
    minstd_rand0 gen2(1);
    for(int i = 0; i < 10; ++i) {
        cout << "2 " << dist2(gen2) << endl;
    }

    return 0;
}

我在gccmsvc上编译。我在std代码上得到了不同的结果!( enter image description here

那么为什么GCC和MSVC std::normal_distribution结果对于相同的种子和生成器是不同的,最重要的是,如何强制它们是相同的?

2 个答案:

答案 0 :(得分:7)

与标准定义的PRN生成器不同,该生成器必须为同一种子生成相同的输出,否则标准不会保留对于分布的任务。来自[rand.dist.general] / 3

  

生成每个指定发行版的算法都是实现定义的。

所以在这种情况下,即使分布必须具有

形式的密度函数

enter image description here

实施如何取决于他们。

获得便携式发行版的唯一方法是自己编写一个或使用第三方库。

答案 1 :(得分:6)

这是有问题的,但遗憾的是,标准没有详细说明在构建(多个)随机分布的数字时要使用的算法,并且有几种有效的替代方案,具有不同的好处。

  

26.6.8.5正态分布[rand.dist.norm]   26.6.8.5.1类模板normal_distribution [rand.dist.norm.normal]

     

normal_distribution随机数分布产生随机   数字x根据概率密度函数分布

     

enter image description here

     

参数μ和也称为此分布的均值和   标准差。

生成正态分布数的最常用算法是 Box-Muller ,但即使使用该算法,也有选项和变体。

标准中甚至明确提到了自由:

  

26.6.8随机数分布类模板[rand.dist]   。 。

     

3   用于产生每个指定分布的算法是   实现定义。

goto的选项是boost random

顺便说一下,正如@Hurkyl所指出的那样:似乎这两个实现实际上是相同的:例如,box-muller生成一对值,其中一个返回,一个被缓存。这两种实现的不同之处仅在于返回了哪些值。

此外,随机数引擎已完全指定,并且将在实现之间提供相同的序列,但需要注意,因为不同的分发也可以消耗不同数量的随机数据以产生结果,这会使引擎不同步。