在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/urandom
或RDRND
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);
我接到一个任务,用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/urandom
或RDRND
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);