【问题标题】:generate random number in c++在 C++ 中生成随机数
【发布时间】:2019-05-15 07:58:10
【问题描述】:

我的任务是在 C++ 中生成数万个随机数。我在 C++ 中搜索了很多关于随机数的信息并查找了 C++ 参考资料,但现在我很困惑。

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

而且我读到“如果您尝试从中获取大量数字,std::random_device 可能会耗尽熵。这可能会导致它阻塞,直到您移动鼠标或其他东西”。这意味着我的程序可能会在某个时间暂停。我怎样才能避免这种情况发生?

【问题讨论】:

  • 你用的是什么编译器? std::random_deviceMinGW损坏
  • 我在ubuntu下使用的是GNU或者g++。
  • 你能发布一些重现问题的简短示例代码吗?
  • 我认为这个答案可能会回答你的一些问题:stackoverflow.com/questions/50662280/…
  • 为什么每次运行的程序都需要不同的设置?

标签: c++ random random-seed


【解决方案1】:

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

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    假设您不需要加密安全的随机数生成,那么您可以使用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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-11
      • 2010-10-11
      • 2012-03-18
      • 2015-07-19
      相关资源
      最近更新 更多