C++11随机数生成器

C++11提供了很多的随机数生成器,可以使用均匀分布,正态分布等方法进行随机。

要想生成随机数,请包含random头文件

C++11的随机数生成比C语言要麻烦,也好用地多。主要有以下概念:

  • 随机数生成器:用来生成随机数的类,相比于C语言,C++通过提供不同的随机数生成器来提供不同的随机数生成算法,让用户对随机数生成的底层算法有更好的选择。
  • 随机数分布:用于按照一定的分布来产生随机数。本质上是通过限定或修改随机数生成器产生的随机数来得到结果的,所以需要一个随机数生成器。

一般来说,得到一个随机数的方式如下:

  1. 首先得得到一个随机数生成器
  2. [可选] 然后可以采用随机数引擎适配器来对生成器进行一些操作
  3. 最后将生成的随机数传入随机数分布来得到随机数。

比较典型的过程如下:

1
2
3
4
5
default_random_engine engin;    //得到一个随机数生成器
engin.seed(time(nullptr)); //传入种子
uniform_int_distribution<int> dist(1, 10);  //得到一个随机分布
for(int i=0;i<100;i++)
    cout<<dist(engin)<<endl;    //随机分布利用随机数生成器生成随机数

随机数生成器

所谓的随机数生成器,其实就是生成随机数的底层算法。

所有的随机数生成器都是要传入种子的,使用成员函数seed(t)即可传入,或者在构造时传入也行。

一般预定义的随机数生成器用的比较多。

随机数生成引擎

是一些通过特定算法生成随机数的类,一共有三个

  • linear_congruential_engine:实现线性同余算法
  • mersenne_twister_engine:实现梅森缠绕器算法
  • subtract_with_carry_engine:实现带进位减(一种延迟斐波那契)算法

这些类都是模板类,其模板参数是要生成的随机数类型和算法需要的一些参数(具体见cppreference)

随机数引擎适配器

用于和随机数引擎搭配使用的适配器类,主要是修改引擎随机出来的随机数,一共有三个:

  • discard_block_engine:舍弃随机数引擎的某些输出
  • independent_bits_engine:将一个随机数引擎的输出打包为指定位数的块
  • shuffle_order_engine:以不同顺序将随机数引擎的结果输出

都是模板类,其模板参数的第一个是随机数引擎的类型,其他的则是需要的参数。

预定义的随机数生成器

这里定义了一些包装了比较流行的算法包的生成器,这里仅举例一些常用的:

  • mt19937:32位梅森缠绕器算法
  • mt1993_64:64位梅森缠绕器算法
  • default_random_engin:默认随机数生成器

一般的用法如下:

1
2
3
random_device d;	// random_device下面会介绍
mt19937 m(d());  //初始化生成器
cout<< mt19937() <<endl; //产生一个随机数

非确定随机数生成器

可以说是真正意义上的随机数(不过具体的还是得看实现,Linux下是通过读取/dev/urandom文件来实现随机的,这就是真正的随机数。而Window则是偷懒直接使用rand_s()函数,这就还是伪随机数)

  • random_device:非确定随机数生成器

一般由于random_device产生随机数的能力很强,我们一般用其产生的随机数当做其他随机数生成器或引擎的种子。

随机数分布

通过限定或者修改随机数生成器的结果来达到一定程度的分布。所以一般参数都需要有一个随机数生成器。

下面列举一些常用的:

  • uniform_int_distribution/uniform_real_distribution:产生一个在区间*[a,b]*上的均匀随机数(分别产生整数和浮点数)
  • binomial_distribution:二项分布
  • poisson_distribution:泊松分布
  • normal_distribution:正态分布

一般的用法如下:

1
2
3
4
random_device d;
mt19937 m(d());	//先得到一个随机数生成器
uniform_int_distribution dist;	//然后得到一个随机数分布
cout << dist(m) <<endl;	//将生成器传入分布,得到最后的随机数
updatedupdated2023-06-182023-06-18