初始化列表中的种子序列初始化

时间:2015-01-20 18:33:32

标签: c++ c++11 random-seed

我目前正在尝试使用接受拒绝方法实现随机数生成器(类)。因此,我需要不同的C ++ 11随机数分布(在我的例子中是正态分布和均匀分布)。我想让随机数尽可能好,因此希望使用以下代码来构建函数:

 [...]
 #include <random>
 #include <vector>
 [...]
 std::vector<int> seeds(16);   
 std::mt19937 mt;
 std::minstd_rand seed_rng(101); // random seed  
 for(size_t i=0;i<16;++i) seeds[i]=seed_rng();
 std::seed_seq seq(seeds.begin(), seeds.end());
 mt.seed(seq);
 rng_normal = std::bind(ndist, std::ref(mt));
 [...]

这完美无缺。但是当我尝试将所有这些现在放在构造函数中时,我不能再使用种子序列的初始化了。我检查了c ++引用,但只遇到了std :: seed_seq :: generate,这不是正确的解决方案 填充向量后,有没有办法在init列表中构造seed_seq? 有关seed_seq的参考,请参见此处:
http://en.cppreference.com/w/cpp/numeric/random/seed_seq
谢谢你,任何建议!

2 个答案:

答案 0 :(得分:0)

假设您不想保留用于构建seed_seq的{​​{1}}实例,您可以执行以下操作:

mt19937

我用[{3}}替换了您的种子( struct foo { std::mt19937 mt; std::normal_distribution<> ndist; std::function<decltype(mt)::result_type()> rng_normal; foo() : mt{make_mersenne_twister()} , rng_normal{std::bind(ndist, std::ref(mt))} {} static std::mt19937 make_mersenne_twister() { std::minstd_rand seed_rng(std::random_device{}()); // random seed std::vector<int> seeds(16); std::generate(seeds.begin(), seeds.end(), seed_rng); std::seed_seq seq(seeds.begin(), seeds.end()); return std::mt19937{seq}; } }; )。

保留101的问题在于它既不可复制也不可移动,因此将其构造委托给像Mersenne Twister这样的函数是不可能的。

std::random_device

答案 1 :(得分:0)

我非常怀疑你的进步非常值得。 std :: mt19937的单值(和默认)构造函数在C ++标准中指定。它等于

static constexpr size_t WS = 32;
static constexpr result_type IM = 1812433253;
static constexpr result_type default_seed = 5489u;

explicit mt19937(result_type value = default_seed)
{
    state[0] = value;
    for (int i = 1; i != state_size; ++i)
    {
        state[i] = i + IM * (state[i - 1] ^ (state[i - 1] >> (WS - 2)));
    }
}

因此,它使用XOR-SHIFT随机数生成器来填充状态数组。鉴于参与该种子算法的人和那些致力于将<random>纳入标准的人,我认为假设他们知道std :: minstd_ran是一个安全的赌注但是发现了上述优良的播种Mersenne Twister。