在C++中生成随机数

generate random number in c++

我接到一个任务,用c++生成数万个随机数。我在 C++ 中搜索了很多关于随机数的内容并查找了 C++ 参考资料,但我现在很困惑。

据我所知,random_device是一个非确定性随机数生成器,但是每次我重新运行我的程序,random_device生成的随机数都是一样的.那么如何为 random_device 设置一个种子,使我重新启动程序时随机数不同?

我读过 "std::random_device could run out of entropy if you try to get a lot of numbers from it. That could cause it to block until you move the mouse or something"。这意味着我的程序可能会在某个时候暂停。我怎样才能避免这种情况发生?

here可以看出std::random_device并不总是保证是非确定性的:

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.

在Linux上,默认使用/dev/urandomRDRND CPU指令,根据here:

The implementations in libc++ and libstdc++ expect token to be the name of a character device that produces random numbers when read from, with the default value "/dev/urandom", although where the CPU instruction RDRND is available, libstdc++ uses that as the default.

不会阻塞。您可以使用方法 here 切换到更安全的设备 /dev/random,但如果没有足够的熵,该设备将被阻止。

在 Windows,我不确定这样的设备,因此它可能会退回到需要某种种子的某些 PRNG。

要跨平台解决问题,如@Binara 所述,您可以使用 <cstdlib> 中的 std::rand。此函数不会阻塞,您可以使用 std::srand(somethingLikeCurrentTime) 使其成为 some-what 非确定性。

如@user1118321 所述,如果您想使用更安全的 PRNG,您可以考虑 std::mersenne_twister_engine 并使用 std::random_device 生成它的种子。建议使用这种方法 here.

假设您不需要加密安全的随机数生成,那么您可以使用 std::mt19937 随机生成器。它是 Meresenne Twister 随机生成器,在重复之前有 219937 次迭代的周期。我过去是这样使用它的:

std::array<int, std::mt19937::state_size> seedData;
std::random_device  randDevice;
std::mt19937 eng;
std::uniform_real_distribution<double> randGen(0, 1);
std::generate_n(seedData.data(), seedData.size(), std::ref(randDevice));
std::seed_seq seq(std::begin(seedData), std::end(seedData));
eng.seed(seq);

这将创建一个包含适当大小的种子的数组。它创建一个随机设备来设置种子。然后它创建一个 mt19937 随机生成器引擎来生成数字。要使用它生成 0 到 1 之间的值,您可以像这样使用 std::uniform_real_distribution

double randVal = randGen(eng);