2015-01-20 172 views
0

我目前正试图实现一个使用验收拒绝方法的随机数发生器(类)。因此我需要不同的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
谢谢您,提供任何建议!

+0

把这段代码放在构造函数中有什么问题?还是你问你可以在初始化列表中完成所有工作? – Praetorian 2015-01-20 18:42:55

+0

@Praetorian是的,对不起。我想在初始化列表中完成一切。 – 2015-01-20 18:50:00

回答

0

假设你不感兴趣,保留用于构建mt19937seed_seq例如,你可以做这样的事情:

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}; 
    } 
}; 

std::random_device替换你的种子(101)。

保留seed_seq的问题在于它既不可复制也不可移动,因此将其构造委派给像我在梅森扭转者那样的功能是不可能的。

Live demo

+0

投票!谢谢,该解决方案实际上应该适合我!我想我会搜索,而seed_seq实际上不可移动也不可复制,因为我猜这是有原因的...... – 2015-01-20 19:30:04

+0

@LeoW。由于你是新人,你的评论表明我的答案有帮助,所以我会向你提供有关[接受有用答案的作品]的常见问题解答(http://meta.stackexchange.com/questions/5234/how-does-accepting -an回答工作)。 – Praetorian 2015-01-27 06:06:36

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,但发现上述优势用于播种梅森扭转者。