我正在寻找标准C ++ 11引擎的一组可移植发行版,例如`std :: mt19937' (见http://en.cppreference.com/w/cpp/numeric/random)。
引擎实现始终如一地执行(即在不同平台上生成相同的序列 - 使用Clang和MSVC进行测试),但分布似乎在不同平台上的实现方式不同。
因此,即使引擎产生相同的序列,似乎分布(例如,std::normal_distribution<double>
)在不同的平台上不使用相同数量的样本(即产生不同的结果),这是在我的情况下是不可接受的。
是否可以使用第三方库,我可以使用C ++ 11随机模板,但这将在流行的平台上提供一致的值(查看GCC,MSVC和Clang / llvm的支持)。
到目前为止我看过的选项是:
我需要制服,正常,毒药和瑞利。
答案 0 :(得分:12)
我创建了自己的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个值 - &gt; 1 sigma内68.159%; 2 sigma内95.437%; 3 sigma内99.747%
正态分布使用Box-Muller方法,根据我到目前为止所读到的方法,它并不是最快的方法,但它的运行速度足以满足我的应用。
统一分布和普通分布都适用于任何C ++ 11引擎(使用std :: mt19937测试),在所有平台上提供相同的序列,这正是我想要的。< / p>