随机设备 vs 默认随机引擎

4
#include <vector>
#include <random>

using namespace std;

int main()
{
    vector<int> coll{1, 2, 3, 4};
    shuffle(coll.begin(), coll.end(), random_device{});

    default_random_engine dre{random_device{}()};
    shuffle(coll.begin(), coll.end(), dre);
}

问题1:两者有什么区别?

shuffle(coll.begin(), coll.end(), random_device{});

shuffle(coll.begin(), coll.end(), dre);

问题2:哪个更好?

1
default_random_engine 是实现定义的 - 这意味着您需要阅读平台文档以查看您正在获取哪个生成器。还有其他标准指定的生成器,请参见:http://en.cppreference.com/w/cpp/numeric/random 建议不要使用 default_random_engine,除非您想要特定于平台的行为。 - Richard Critten
2个回答

7
问题1:两者有何不同?
std::random_device概念上产生真正的随机数。一些实现会在您耗尽系统的熵源时停止,因此这个版本可能表现不佳。
std::default_random_engine是一个伪随机引擎。一旦种子被赋值为一个随机数,预测下一个数字将非常困难(但不是不可能)。
还有另一个微妙的区别。如果无法生成随机数,std::random_device::operator()将抛出异常。
问题2:哪个更好?
这取决于情况。对于大多数情况,您可能需要使用由随机数种子生成的伪随机引擎的性能和时间确定性,因此第二个选项是更好的选择。

1
有一件有点烦人的事情是,尽管文档说 std::random_device 应该是真正的随机数,但当我查看我的 libc++ 头文件时,它实际上是 /dev/urandom 而不是 /dev/random,因此从技术上讲也是伪随机数,可能不会阻塞。但在 Windows 上,我想它是一些加密 API?我觉得 std::random_device 目前没有很好地规定。另外,在我看来,没有无异常接口也是不好的。最近我的倾向是绕过它直接使用 /dev/random,除非我知道我在 Windows 上,然后使用 random_device - Chris Beck
@ChrisBeck 至少在Linux上,/dev/urandom 在功能上与 /dev/random 相同,只是后者在熵池耗尽时不会阻塞以获取安全数字,而是使用伪随机数生成器。熵池非常大,因此任何利用代码都需要耗尽熵池并预测何时熵池已经用尽并正在生成更多的内容。 - colintheshots

4

random_devicedefault_random_engine都是实现定义的。如果可用,random_device应该提供不确定性的随机性源,但在某些实现中它也可能是一个伪随机数生成器。如果您想要不可预测的随机数(现在大多数计算机都有硬件熵源),请使用random_device。如果您想要伪随机数,您可能会使用特定的算法之一,例如mersenne_twister_engine

我猜default_random_engine是您在不关心如何获得随机数的情况下使用的东西。我怀疑它会在大多数情况下使用randlinear_congruential_engine

我认为“哪个更好”这个问题不能客观地回答。它取决于您要使用随机数做什么。如果它们是某些加密过程的随机源,我认为default_random_engine是一个糟糕的选择,尽管我不是安全专家,所以我不确定即使random_device是否足够好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接