【发布时间】:2020-09-03 16:27:15
【问题描述】:
我正在尝试构建一个简单的随机数生成器,但我想确保 random_device 正常工作。我从以下代码开始:
#include <random>
#include <chrono>
class Generator {
public:
Generator()
:
m_DeviceSeed(rd()),
m_TimeSeed(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
rng(m_DeviceSeed)
{
if (rd.entropy() == 0.0) {
rng.seed((unsigned)m_TimeSeed);
}
}
private:
//Vars
std::random_device rd;
unsigned int m_DeviceSeed;
unsigned long long m_TimeSeed;
std::mt19937 rng;
};
我曾看到“std::chrono::high_resolution_clock::now().time_since_epoch().count()”被推荐为 random_device 的替代品,我认为检查熵可以让我将其用作后备;但是,这是用 Visual Studio 编写的,显然这意味着熵总是显示 32,无论它是否为真。
那么,我的问题是这样的:在没有熵测试手段的情况下播种 std::mt19937 的最稳健方法是什么? chrono 更好还是 random_device 更好?还是某种组合,或完全是其他选择?
基于此:The implementation of random_device in VS2010?
在大多数情况下,random_device 似乎是播种或生成种子序列的安全选择,但我想确定一下。
【问题讨论】:
-
使用当前纪元?
-
如果你不能依赖熵,那就不要使用它。您的备份计划应该足以在所有情况下使用。
-
注意,在
m_DeviceSeed的构造器初始化列表项中,rd还没有被构造,所以rd()不一定做任何有意义的事情。 -
“所以,我的问题是:在没有熵测试手段的情况下,最稳健的播种 std::mt19937 的方法是什么?” - 我会使用std::seed_seq 进行播种,该std::seed_seq 由一些相当随机的东西构成,例如当前时间(尽可能精确)、当前进程ID、内存中
main的地址、用户ID当前用户等,然后填写来自std::random_device的输出。 -
一种方法是正确编写代码。惠特:
m_DeviceSeed(rd())这是 UB。rd尚未初始化,因为成员是按声明顺序初始化的。
标签: c++ random visual-c++ c++17 mt19937