C++ C++;11不同平台的随机数分布不一致——有哪些替代方案?

C++ C++;11不同平台的随机数分布不一致——有哪些替代方案?,c++,c++11,boost,random,libstdc++,C++,C++11,Boost,Random,Libstdc++,我正在为标准C++11引擎寻找一组可移植的发行版,如“std::mt19937”(请参阅) 引擎实现执行一致(即,在不同平台上生成相同的序列-使用Clang和MSVC进行测试),但在不同平台上实现的发行版似乎不同 因此,即使引擎产生相同的序列,分布(例如,std::normal_distribution)似乎在不同的平台上不使用相同数量的样本(即产生不同的结果),这在我的情况下是不可接受的 我是否可以使用一个第三方库来遵循C++11随机模板,但它将在流行的平台上提供一致的值(查看跨GCC、MSV

我正在为标准C++11引擎寻找一组可移植的发行版,如“std::mt19937”(请参阅)

引擎实现执行一致(即,在不同平台上生成相同的序列-使用Clang和MSVC进行测试),但在不同平台上实现的发行版似乎不同

因此,即使引擎产生相同的序列,分布(例如,
std::normal_distribution
)似乎在不同的平台上不使用相同数量的样本(即产生不同的结果),这在我的情况下是不可接受的

我是否可以使用一个第三方库来遵循C++11随机模板,但它将在流行的平台上提供一致的值(查看跨GCC、MSVC和Clang/llvm的支持)

到目前为止,我所看到的选项有:

  • Boost.random(有点重,但值得一试,因为它与c++11对应的版本非常匹配)
  • 从libstd++进行克隆(同样值得,而且可能是可移植的,但是提取特定函数可能并不简单)
  • 创建我自己的C++11类随机分布

我需要统一、正常、毒药和瑞利。

我创建了自己的C++11发行版:

template <typename T>
class UniformRealDistribution
{
 public:
    typedef T result_type;

 public:
    UniformRealDistribution(T _a = 0.0, T _b = 1.0)
        :m_a(_a),
         m_b(_b)
    {}

    void reset() {}

    template <class Generator>
    T operator()(Generator &_g)
    {
        double dScale = (m_b - m_a) / ((T)(_g.max() - _g.min()) + (T)1); 
        return (_g() - _g.min()) * dScale  + m_a;
    }

    T a() const {return m_a;}
    T b() const {return m_b;}

 protected:
    T       m_a;
    T       m_b;
};

template <typename T>
class NormalDistribution
{
 public:
    typedef T result_type;

 public:
    NormalDistribution(T _mean = 0.0, T _stddev = 1.0)
        :m_mean(_mean),
         m_stddev(_stddev)
    {}

    void reset()
    {
        m_distU1.reset();
    }

    template <class Generator>
    T operator()(Generator &_g)
    {
        // Use Box-Muller algorithm
        const double pi = 3.14159265358979323846264338327950288419716939937511;
        double u1 = m_distU1(_g);
        double u2 = m_distU1(_g);
        double r = sqrt(-2.0 * log(u1));
        return m_mean + m_stddev * r * sin(2.0 * pi * u2);
    }

    T mean() const {return m_mean;}
    T stddev() const {return m_stddev;}

protected:
    T                           m_mean;
    T                           m_stddev;
    UniformRealDistribution<T>  m_distU1;
};
模板
类统一分布
{
公众:
typedef T result_type;
公众:
统一分布(T_a=0.0,T_b=1.0)
:m_a(_a),
m_b(_b)
{}
void reset(){}
模板
T运算符()(生成器和)
{
双D标度=(m_b-m_a)/(T)(最大值-(最小值)()+(T)1);
返回(_g()-_g.min())*dScale+ma;
}
T a()常量{return m_a;}
tb()常数{return m_b;}
受保护的:
T m_a;
T m_b;
};
模板
类正态分布
{
公众:
typedef T result_type;
公众:
正态分布(T平均值=0.0,T标准差=1.0)
:m_平均值(_平均值),
m_stddev(_stddev)
{}
无效重置()
{
m_distU1.reset();
}
模板
T运算符()(生成器和)
{
//使用Box-Muller算法
常数双pi=3.14159265358979323846264338327950288419716939937511;
双u1=m_distU1(_g);
双u2=m_distU1(_g);
双r=sqrt(-2.0*log(u1));
返回m_均值+m_标准差*r*sin(2.0*pi*u2);
}
T mean()常数{返回m_mean;}
T stddev()常量{return m_stddev;}
受保护的:
T m_平均;
T m_stddev;
统一分布图1;
};
均匀分布似乎提供了良好的结果,而正态分布则提供了非常好的结果:

100000个值->1西格玛内68.159%;2西格玛内95.437%;99.747%在3西格玛范围内

正态分布使用Box-Muller方法,根据我到目前为止所读的内容,它不是最快的方法,但对于我的应用程序来说,它运行得更快


均匀分布和正态分布都应该适用于任何C++11引擎(使用std::mt19937测试),并且在所有平台上提供相同的序列,这正是我想要的。

库是您需要的吗?@shuttle87,我一直在慢慢地从我的代码库中弹出所有的boost,所以我不想再把boost库拉回来。哦,我完全理解不想因为依赖的大小而依赖boost。然而,boost库的大部分重量来自于跨平台,这在您所询问的用例中非常有用。如果有一个较小的库只包含随机数功能,我也想知道这一点。@shuttle87是boost.random,保证在不同的平台上提供相同的结果?遇到这样一个问题:它看起来非常完整,但是我必须调整发行版以适应C++11引擎。这只适用于浮点吗?我在我的一个项目中尝试了这一点,我给出了整数的范围,我得到的“浮点异常”仅用于浮点,但我不明白为什么会得到异常。当给定一个整数时,你会得到一个除以零的异常。是的,正态分布依赖于下面真正的均匀分布。看见