在C ++中生成随机数

时间:2018-12-14 03:21:57

标签: c++ random random-seed

我得到一个在c ++中生成数万个随机数的任务。我已经在c ++中搜索了很多有关随机数的内容,并查找了c ++参考,但是现在我很困惑。

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

我读到“如果您尝试从中获取很多数字,std :: random_device可能会用尽熵。这可能会导致其阻塞,直到您移动鼠标或其他东西为止”。这意味着我的程序可能会在某些时候暂停。我如何避免这种情况发生?

3 个答案:

答案 0 :(得分:1)

here,您可以看到std::random_device并不总是保证是不确定的:

  

std :: random_device可以根据实现定义的伪随机数引擎实现,如果不确定的源(例如,硬件设备)对实现不可用。在这种情况下,每个std :: random_device对象都可能生成相同的数字序列

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

  

libc ++和libstdc ++中的实现期望令牌是从中读取时会产生随机数的字符设备的名称,其默认值为“ / dev / urandom” ,尽管其中CPU指令RDRND可用,libstdc ++将其用作默认指令

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

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

要跨平台解决问题,如@Binara所述,您可以使用std::rand中的<cstdlib>。此功能不会被阻止,您可以使用std::srand(somethingLikeCurrentTime)使其具有不确定性。

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

答案 1 :(得分:1)

假设您不需要加密安全的随机数生成,则可以使用std::mt19937随机生成器。 Meresenne Twister随机生成器在重复之前要进行2 19937 次迭代。我过去曾经这样使用它:

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);

答案 2 :(得分:-3)

只需扩展上一个答案即可。如果要生成一定范围内的随机数。您可以使用

srand(time(NULL));
rand() % n + 1;

其中n是要生成的最大值。