可以直接使用random_device生成的624个整数作为mt19937的种子吗?我应该使用seed_seq吗?
class RDSeq {
public:
template <typename It>
void generate (It first, It last) const {
std::random_device rd {};
std::generate(first, last, std::ref(rd));
}
};
std::mt19937 random {};
RDSeq seq {};
random.seed(seq);发布于 2019-11-01 11:09:07
简而言之,你不需要这样做,所有的Mersenne Twister构造函数都会在你给它的任何状态下调用seed_seq,而不管它的大小。
这是我为填充Mersenne Twister的初始状态而编写的代码。
template <typename T = std::uint32_t, typename Enable = void>
class Mersenne;
template <typename T>
using AllowForUnsigned = std::enable_if_t<std::is_unsigned_v<T>>;
template <typename T>
class Mersenne<T, AllowForUnsigned<T>>
{
public:
Mersenne();
T operator()();
using result_type = T;
static constexpr result_type min();
static constexpr result_type max();
private:
using Twister = std::conditional_t<sizeof(T) <= 4, std::mt19937, std::mt19937_64>;
Twister engine_;
};
// Mersenne class implementation
template <typename T>
Mersenne<T, AllowForUnsigned<T>>::Mersenne()
{
// Proper seeding of mt19937 taken from:
// https://kristerw.blogspot.com/2017/05/seeding-stdmt19937-random-number-engine.html
// Body walkthrough at end of file
std::random_device rd;
std::array<T, Twister::state_size> seed_data;
std::generate_n(std::begin(seed_data), seed_data.size(), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
engine_ = Twister(seq);
}这是一篇博客文章的clickable link,我将其改编成一个类,用于播种Mersenne Twister。这个类的核心是在我上面包含的默认构造函数中。这个想法就像你所说的,用种子数据填充整个19937位状态。
完整的实现是here。大多数其他东西都是为了提供与<random>中的发行版的兼容性。有很多针对课堂环境的评论。值得一提的是,除非random_device能够获得真正的熵,否则它将使用确定性方法来创建种子值。seed_seq也是确定性的,但如果random_device至少有一个熵源,它可以在一定程度上得到缓解。注意到:Mersenne Twister构造器也会调用seed_seq,所以即使您只提供了32位的状态,也会生成一个完整的状态,但这并不理想:link
简而言之,只提供32位的初始状态将导致PRNG永远不会生成某些值。人们可能会争辩说,对于游乐场的目的来说,它已经足够了,或者如果你总是通过一个发行版来过滤它,那么它就不那么重要了,我认为这是一个公平的观点。但与此同时,永远不会选择某些值的PRNG与rand()一样糟糕。
其他人也会说,一旦你开始关心这一点,C++标准库(如果你说<random>,这里的人会发疯,尽管他们在技术上是正确的,但我从来没有进行过真诚的技术讨论),STL可能根本不适合你。它们不是加密安全的PRNG,并且很容易被误用,比如被允许对具有19937位状态大小的PRNG使用32位。
编辑:我的构造函数构建了一个seed_seq;我只是试图保证调用一个特定的构造函数。
https://stackoverflow.com/questions/58653190
复制相似问题