与C++11之前的随机数生成器相比,C++11的随机数生成器要复杂得多。 这是因为相比于前面两个可以获取随机数的函数srand和rand,C++11提供了太多的选择和东西。

随机数生成算法:

随机数生成算法有很多种,C++11之前的C/C++只使用了一种。 C++11提供了以下三个选项:

线性同余法

梅森旋转法

落后

这三种算法都是使用C++11中的模板实现的。 如果我们要使用这三个模板类,就必须自己实例化它们。 但这些实例化参数都是这些算法中使用的参数。 如果你不了解算法的原理,你真的不知道需要哪些参数才能得到更好的随机序列。 所以我们卑微的程序员不能使用这些模板类。 C++11标准也想到了这一点,所以它为我们预定义了一些随机数类。 这些随机数类使用更好的参数来实例化上面的三个模板类。 注意:在C++11中,这些随机数生成器称为()。

下图列出了一些实例化的随机数类:

当然,我们不需要关心具体使用的参数,直接使用即可。

在上图的左上角,还可以看到一辆e级。 它也是一个实例化类。 之所以不分为这三种算法,是因为它的实现是由编译器厂商决定的。 有些可以使用ine来实现,有些可以使用ine来实现。 这种现象在C/C++中比较常见。 然而,对于其他类,C++11明确规定了使用哪些算法和参数来实现它们。

好吧,说了这么多,让我们继续前面的例子。

#include
#include
 
usingstd::cout;
usingstd::endl;
usingstd::cin;
 
intmain()
{
    std::default_random_engine random;
 
    for(int i = 0; i < 20; ++i)
        cout<

在C++11中,随机数在头文件中定义。 除了e之外,其他实例化随机数类的名字都很奇怪,所以这个很好用。 从示例中可以看到,下一个随机数是通过()函数获得的。

熟悉 srand 的程序员肯定会发现这里并没有使用随机数种子。 其实这里使用的是默认种子,默认种子的值可以通过这种类型的公共静态常量来获取。 如果你想为这个类设置自己的种子,你可以在构造函数中传入一个参数。 您还可以在构造后调用seed()成员函数来设置种子。

生成均匀分布的随机数:

上面例子中生成的随机数会比较大,如果我们只想生成0到100之间的随机数。按照我们之前的做法,我们直接()0。 这种做法是不好的。 原因可以参见《C++》第7.4.4节。

C++11 也知道这一点,这使得 C++11 的随机数更加复杂。

我们通常所说的生成随机数,隐含的意思就是生成均匀分布的随机数。 学过概率论的同学都知道,除了均匀分布之外,还有很多分布,比如正态分布、泊松分布等,之前在网上看到过网友是如何利用rand()函数生成的随机数来创建这些分布的。 现在不需要程序员来做这项工作,C++11 标准提供了这些发行版。

C++11提供的均匀分布的模板类是:概念和执行。 前面的模板类名中的int并不是代表整数,而是整数。 因为是模板类c++ 随机数生成器,所以可以用int、long、short等整数类型来实例化。后者表示浮点数模板类,可以用float和.float来实例化。 使用示例如下:

#include
#include
#include
 
using std::cout;
using std::endl;
using std::cin;
 
 
int main()
{
    std::default_random_engine random(time(NULL));
    std::uniform_int_distribution dis1(0, 100);
   std::uniform_real_distribution dis2(0.0, 1.0);
 
    for(int i = 0; i < 10; ++i)
        cout<

可以看到,在的构造函数中,参数指定了随机数的范围。 执行的随机数范围不是半开范围[),而是[],但执行时是半开范围[)。 也就是说,上面的例子中,可以生成100,但是不会生成1.0。 不得不说,这颠覆了之前的认识。 对于e,它生成的随机数范围在[min(), max()]之间,其中min()和max()是它的两个成员函数。 同样,它也是一个非半开范围。对于浮点数,如果确实想生成[0.0, 1.0]范围内的数字,可以使用


#include
#include
std::uniform_real_distribution dis2(0, std::nextafter(1,DBL_MAX));

如果使用无参数构造函数,则其随机数的范围为[0,::max()],即0到对应实例化类型可以表示的更大值。 对于 ution 的无参数构造函数,它是 [0, 1)。

概率分布类型:

C++11提供的概率分布类型如下:

平均分配:

整数均匀分布

运算浮点数均匀分布

伯努利型分布:(只有两个结果是/否,概率为一个 p 和一个 1-p)

伯努利分布

n 二项式分布

n几何分布

负二项分布

速度-:

泊松分布

指数分布

伽玛分布

威布尔分布

极值分布

正态分布相关:

正态分布

卡方分布

柯西分布

n F 分布

本体分布

段分布相关:

n 离散分布

分段常数分布

分段线性分布

这些概率分布函数都有参数,只需在类的构造函数中传递参数即可。

下面是泊松分布的示例


#include
#include
#include
#include
 
intmain()
{
  const int nrolls = 10000; // number ofexperiments
  const int nstars = 100;   // maximum number of stars to distribute
 
  int parameter = 4;
 
  std::minstd_rand engine(time(NULL));
  std::poisson_distributiondistribution(parameter);
 
  int p[20]={};
 
  for (int i=0; i

某输出结果为:

也许大家都忘记了泊松分布。 看看下面的图片。

真随机数:

C++11还提供了随机数类。 它不是通过一定的数学算法得到的随机序列,而是通过读取文件得到的,具体实现取决于读取哪个文件(Linux可以通过读取/dev/文件来获取)。 文件的内容是随机的,因为文件内容是计算机系统的熵(熵指的是系统的无序程度)。 也是当前系统的环境噪声。 系统噪声可以通过许多参数来评估,例如内存使用情况、文件使用情况、不同类型进程的数量等。Linux 熵来自键盘计时、鼠标移动等。

然而,gcc 似乎并没有很好地实现这个类。 我手里的.9.0不是随机的,每次运行都得到相同的序列。

未经允许不得转载! 作者:admin,转载或复制请以超链接形式并注明出处天心神途传奇手游发布网

原文地址:《C++11随机数学习》发布于:2024-03-15

发表评论

表情:
验证码
评论列表 (暂无评论,25人围观)

还没有评论,来说两句吧...