与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
还没有评论,来说两句吧...