我似乎看到了很多答案,其中有人建议使用 <random>
生成随机数,通常还有这样的代码:
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 5);
dis(gen);
通常情况下,这会取代某种“令人厌恶的东西”,比如:
srand(time(NULL));
rand()%6;
我们可以用旧的方法来证明 time(NULL)
提供了低熵,time(NULL)
是可预测的,并且最终的结果是非均匀的。
但是所有这些对于新的方式来说都是真实的: 它只是有一个更闪亮的表面。
返回单个 unsigned int
。它至少有16位,可能有32位。这还不足以播种机器翻译公司19937年的州。
使用 std::mt19937 gen(rd());gen()
(使用32位播种并查看第一个输出)不会给出一个很好的输出分布。7和13不可能是第一个输出。两粒种子产生0。12粒种子产生1226181350。(林克)
std::random_device
可以(有时也是)实现为带有固定种子的简单 PRNG。因此,它可能在每次运行时产生相同的序列。(林克)这比 time(NULL)
还要糟糕。
更糟糕的是,尽管前面的代码片段包含一些问题,但是复制和粘贴它们是非常容易的。一些解决这个问题的方案需要获得 很大 图书馆,这可能并不适合每个人。
有鉴于此,我的问题是 如何在 C + + 中简洁、可移植和彻底地播种 mt19937 PRNG?
鉴于上述问题,一个不错的答案是:
std::random_device
或 time(NULL)
作为熵的来源。想法
我目前的想法是,std::random_device
的输出可以与 time(NULL)
、从 地址空间随机化地址空间随机化得到的值和一个硬编码常数(可以在分配过程中设置)混合(也许通过异或) ,以获得最佳效果。
std::random_device::entropy()
没有提供了一个很好的迹象,什么 std::random_device
可能会或可能不会做。