如何以安全便携的方式播种随机数生成器?

How to seed a random number generator in a safe and portable way?

背景:

, it is recommended to use a std::random_device instead of the time to seed a random number generator. If we take a look at the related documentation 开始,我们可以读到:

std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.

强调我的

现在让我们考虑以下示例:

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution distr(0, 9);

    // Print a sequence of 10 uniformly distributed random integers
    for(std::size_t i = 0; i < 10; ++i)
        std::cout << distr(gen) << ' ';

    return 0;
}

如果 system/platform 不提供非确定性来源,这个程序 may/will 总是为每个 运行 生成相同的数字序列(实际上是我的情况平台)。

在这种情况下,std::random_device 比使用当前时间播种随机数生成器更糟糕:

std::mt199937 gen(std::chrono::high_resolution_clock::now().time_since_epoch().count()); // time seed

问题:

我担心的是,如果有人想编写一个依赖于一些随机生成的数字的程序并且需要:

  1. 便于携带
  2. 保证非确定性随机性

那么 std::random_device 将不合适。
另一方面,始终使用时间种子会令人非常沮丧 "solution",因为如果给定平台具有可用的不确定源,则 std::random_device 将是 "safer".

问题:

我的问题分为两部分:

  1. 用户空间
    • 有没有一种可移植的方法来检查当前平台上是否可以使用这种不确定的源?
  2. 编译器端
    • 如果主机平台没有可用的非确定性源,是否允许编译器用时间种子替换 std::random_device 种子?或者标准中是否有某些内容会阻止此类替换?
    • 如果标准不禁止这种行为,编译器不实现它的原因是什么?

也许这些应该是 2 或 3 个单独的问题。由于背景和问题很常见,为了主题的完整性,我在同一个 post 中询问了他们。如果我必须将它们分成单独的问题,请告诉我。

Is there a portable way to check if such a non-deterministic source is available on the current platform?

您可以使用 std::random_deviceentropy 成员函数来检查源是否是非确定性的。不幸的是,它不是 static constexpr 函数,所以你必须使用像

这样的常规 if 语句
int main()
{
    std::random_device rd;
    std::size_t seed;
    if (rd.entropy())
        seed = rd();
    else
        seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    std::mt19937 gen(seed);
    std::uniform_int_distribution distr(0, 9);

    // Print a sequence of 10 uniformly distributed random integers
    for(std::size_t i = 0; i < 10; ++i)
        std::cout << distr(gen) << ' ';

    return 0;
}

Are compilers allowed to replace std::random_device seeds by time seeds if the host platform has no non-deterministic source available ? Or is there something in the standard that would prevent such a replacement?

这会改变程序的可观察行为,所以不,编译器不能那样做。