繁体   English   中英

随机数生成,两种不同的方法?

[英]Random number generation, two different methods?

有谁知道以下代码中使用的两种随机数生成方法之间的区别? 我的怀疑是第一种情况可能在计算上更昂贵,因为每次生成随机数时它都会从/dev/urandom获取新种子。 如果我在这些示例中正确生成随机数,也感谢任何评论。

我很困惑,因为uniform_int_distribution指定了template<class URNG> result_type operator()(URNG& g); 在某些示例中,我看到传递的参数类型为default_random_engine和其他时间random_device 这增加了对default_random_engine实际作用的混淆。

比如我见过的方法1:

#include <iostream>
#include <random>
#include <map>
using namespace std;

int main()
{
    random_device rd;
    uniform_int_distribution<int> p{0,9};

    map<int,int> m;
    for (int i=0; i < 100; ++i) {
        m[p(rd)]++;
    }

    for (map<int,int>::iterator it = m.begin();
         it != m.end(); ++it)
        cout << it->first << ", " << it->second << '\n';
    
    return 0;
}

方法2,

#include <iostream>
#include <random>
#include <map>
using namespace std;

int main()
{
    random_device rd;
    default_random_engine gen(rd());
    uniform_int_distribution<int> p{0,9};

    map<int,int> m;
    for (int i=0; i < 100; ++i) {
        m[p(gen)]++;
    }

    for (map<int,int>::iterator it = m.begin();
         it != m.end(); ++it)
        cout << it->first << ", " << it->second << '\n';
    
    return 0;
}

第一种方法是不好的做法,第二种方法是首选。 虽然,在第二种方法中,通常不推荐default_random_engine ,除非它是出于实验或其他一些非重要原因。 最大的原因是它是实现定义的,所以它会根据编译器而有所不同,而且它通常根本不健壮,只是简单。

第一种方法不好的原因是std::random_device轮询硬件的真正随机性来源。 这是一个有限的供应。 更好的做法是将其用作伪随机数生成器 (PRNG) 的完全不可预测的种子。 这就是为什么第二个例子更好。

我对您的第二个示例进行了一些更改。 主要的变化是我不需要声明一个random_device来坐在堆栈上,我使用std::mt19937这可能是你在 C++ 代码中看到的最常见的 PRNG。

没有一个 C++ 标准库 PRNG 被认为足以用于加密目的; 你需要一个外部库。

#include <iostream>
#include <map>
#include <random>

int main() {
  std::mt19937 gen(std::random_device{}());
  std::uniform_int_distribution<int> p{0, 9};

  std::map<int, int> m;
  for (int i = 0; i < 100; ++i) {
    m[p(gen)]++;
  }

  for (auto it = m.begin(); it != m.end(); ++it) {
    std::cout << it->first << ", " << it->second << '\n';
  }

  return 0;
}

std 库提供了一组预定义的随机数生成器,它们为生成的值提供了某些保证。 其中之一是实现定义的default_random_engine (因此您需要检查库的供应商如何实现它)。

要拥有可靠的生成器(不同供应商之间的结果一致),您可以选择其他生成器之一,例如mt19937

您从random_device获得的随机数通常仅用作所选随机数生成器的种子。 对于random_device你有一个与default_random_engine类似的问题,因为它没有指定如何生成值。

这背后的想法是random_device通常为种子提供足够好的值,但对于适当的生成器来说不够好。

如果您知道您的程序正在运行的特定硬件和库,并且您知道random_device基于良好的来源创建随机数,那么它可能是一个选项,但如果您创建一个在不同操作系统上使用且未知的应用程序硬件,那么random_device将不会作为生成器的选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM