c++ - 如何在构造函数中构造预定义的随机数生成器和种子序列?

标签 c++ random c++17

背景

我正在构建一个离散的选择器,例如给定一个序列,它根据给定的权重随机选择一个具有概率的元素。您可以将其视为一对 PredefinedRandomGeneratorstd::discrete_distribution。我希望选择器是便携的,并提供合理的熵。它将不会用于密码上下文,我只是想要更好的随机性(抱歉,如果我搞砸了这里的术语)。

问题

Windows 上的 MinGW 上的

std:random_device 总是产生相同的数字。作为解决方法,我使用

//assume using namespace std::chrono
std::seed_seq seq{std::random_device{}(), 
                  duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count(),
                  42};

问题是 PredefinedRandomGenerator 的构造函数需要左值引用,所以我无法在成员初始化列表中初始化它,如下所示:

template <typename InputIterator>
discrete_selector(InputIterator weights_first,
                  InputIterator weights_last):
        generator(std::seed_seq{/*...*/}),
        distribution(weights_first, weights_last)
{}

所以现在至少有一个或多或少的随机数来源。

我尝试了什么

//somewhere in namespace details
std::seed_seq& get_new_sequence()
{
    static std::unique_ptr<std::seed_seq> sequence;
    sequence = std::make_unique<std::seed_seq>(std::random_device{}(), 
                                            duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count(),
                                            42);
    return *sequence;
}

以上应该可行,但我相信应该有更好的方法来做到这一点。


附带问题

为什么构造函数通过左值引用获取 std::seed_seq?它至少可以使用右值引用。

最佳答案

我通常做的是使用 lambda。

generator([]() -> auto& {
    static std::seed_seq seq(std::random_device()(), 
              duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count(),
              42);
    return seq;
}())

如果您愿意,您始终可以像以前那样将 lambda 放在另一个私有(private)函数中,这对于所有意图和目的来说也很好。


或者,像 tree with eyes说,你可以在构造函数中初始化种子。 :)

关于c++ - 如何在构造函数中构造预定义的随机数生成器和种子序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48008489/

相关文章:

从函数指针的参数推导 C++ 模板类型

c++ - 未定义、删除、未声明的函数

python - 将列表随机划分为两个互补的子列表

r - 在 R : Avoid duplicates in selection from many rows 中

python - 有谁知道一种打乱列表中元素的方法?

c++ - 是否可以从构造函数自动推导出基类模板参数?

c++ - 指向 lambda 的函数指针目标的生命周期是多少?

c++ - 类型转换构造函数参数的问题

c++ - g++ 警告标志以避免 bool 到 double 转换

c++ - 有没有办法以 vector 形式访问内存映射?