我们知道,C 中的随机数函数只有一个 rand( )
,想生成某一区间范围内的随机数乃至随机的浮点数都十分麻烦。
而 C++11 中提供的 random
库解决了这一问题,它能让我们方便地生成需要的随机值。
下面将介绍如何利用 random
库中的组件生成符合条件的随机数。
random
库中的组件分为两类——随机数引擎类和随机数分布类。
随机数引擎类是可以独立运行的随机数发生器,它以均匀的概率生成某一类型的随机数,但无法指定随机数的范围、概率等信息。因此,它也被称为“原始随机数发生器”,由于不能指定生成随机数的范围,它通常不会被单独使用。
随机数分布类是一个需要于随机数引擎类的支持才能运行的类,但是它能根据用户的需求利用随机数引擎生成符合条件的随机数,例如某一区间、某一分布概率的随机数。
所有随机数引擎类都支持的操作如下:
名称 | 功能 |
---|---|
Engine e | 创建一个引擎。 |
Engine e(s) | 创建一个引擎,并用 s 作为种子。 |
e.seed(s) | 使用种子 s 充值 e 的状态。 |
e.min( ), e.max( ) | e 能生成的最小值和最大值。 |
e.discard(u) | 将 e 推进 u 步(u 的类型为 unsigned long long)。 |
下表随机数分布类共有的操作:
名称 | 功能 |
---|---|
U u | 创建一个分布类 u 。 |
u(e) | 用随机数引擎 e 生成随机数(u 代表随机数分布类)。 |
u.min( ) | u 能生成的最小值。 |
u.max( ) | u 能生成的最大值。 |
u.reset( ) | 重置 u 的状态,使随后 u 生成的值不受之前的值影响 。 |
随机非负数——default_random_engine
default_random_engine
是一个随机数引擎类。它定义的调用运算符返回一个随机的 unsigned
类型的值。
因此,若想生成 10 个随机非负数并输出,程序可以这么写:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
for(int i=0; i<10; ++i)
cout<<e( )<<endl;
return 0;
}
在我们的系统中,测试结果为:
16807
282475249
1622650073
984943658
1144108930
470211272
101027544
1457850878
1458777923
2007237709
可以看出,还是比较“随机”的。
当然,default_random_engine
也只是一个伪随机数发生器,如果在运行一次程序,得到结果将还是这几个数。
若想令每次运行程序时的生成结果不同,可以为其设置较为随机的种子,比如当前系统的时间。
特定范围的非负数——uniform_int_distribution
uniform_int_distribution
是一个随机数分布类,也是个模板类,模板参数为生成随机数的类型(不过只能是 int、unsigned、short、unsigned short、long、unsigned long、long long、unsigned long long 中的一种)。它的构造函数接受两个值,表示随机数的分布范围(闭区间)。
因此,一个生成 0 到 9 的随机数程序可以这么写:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
uniform_int_distribution<unsigned> u(0, 9);
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我们的系统中,它的生成结果为:
0
1
7
4
5
2
0
6
6
9
随机浮点数——uniform_real_distribution
uniform_real_distribution
是一个随机数分布类,它也是模板类,参数表示随机数类型(可选类型为 float、double、long double)。构造函数也需要最大值和最小值作为参数。
下面是一个生成 10 个 0~1 之间的随机浮点数的例子:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
uniform_real_distribution<double> u(0.0, 1.0);
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我们的系统上的结果为:
0.131538
0.45865
0.218959
0.678865
0.934693
0.519416
0.0345721
0.5297
0.00769819
0.0668422
随机布尔值——bernoulli_distribution
bernoulli_distribution
是一个分布类,但它不是模板类。它的构造函数只有一个参数,表示该类返回 true 的概率,该参数默认为 0.5 ,即返回 true 和 false 的概率相等。
下面是一个生成 10 个随机布尔值的例子:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
bernoulli_distribution u;
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我们的系统上的结果为:
1
1
1
0
0
0
1
0
1
1
总结
常用的随机数类如下:
-
default_random_engine
:随机非负数(不建议单独使用)。 -
uniform_int_distribution
:指定范围的随机非负数。 -
uniform_real_distribution
:指定范围的随机实数。 -
bernoulli_distribution
:指定概率的随机布尔值。
事实上,random
库的功能极其丰富,其中的随机数引擎不止有 default_random_engine
一个,分布类也远远不止上述三个。它还能进行泊松分布、正态分布、抽样分等高级的随机数功能,想详细了解这些内容请去查阅其他资料。我可能要等好久才能把这些内容补上。