C++11 随机数分布在各个平台上并不一致——有什么替代方案

C++11 random number distributions are not consistent across platforms -- what alternatives are there?

本文关键字:不一致 什么 方案 分布 随机数 平台 C++11      更新时间:2023-10-16

我正在寻找一组用于标准 C++11 引擎的可移植发行版,例如"std::mt19937"(请参阅 http://en.cppreference.com/w/cpp/numeric/random)。

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

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

是否有我可以使用遵循 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;
};

均匀分布似乎提供了很好的结果,正态分布提供了非常好的结果:

100000 个值 -> 1 西格玛内为 68.159%;2 西格玛以内为 95.437%;3 西格玛以内为 99.747%

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

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