- C++11之前,没有自带的random函数,要生成随机数,普遍采用rand和srand()。
- C++11之后,内部提供了强大的随机数库Random。
rand()
其内部实现是用线性同余法做的,生成是可看做一定范围内随机的伪随机数,其最大范围和系统相关。
通用公式:
- a + rand() % n;其中的a是起始值,n是整数的范围。
- 或 a+(int)b * rand() / (RAND_MAX + 1)。
- 要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
for (int i = 0; i < 10; i++)//输出十次
{
cout << rand()%100<< " ";//范围在[0,100)的随机数
}
return 0;
}
注意:没有随机种子,多次重复运行,产生的随机数结果是相同的。
srand()
srand()可用来设置rand()产生随机数时的随机数种子。
- 通过设置不同的种子,我们可以获取不同的随机数序列。
- 例如,使用srand((int)(time(NULL))的方法,利用系统时钟,产生不同的随机数种子。不过要调用time(),需要加入头文件ctime。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 10; i++)//产生十次
{
cout << rand()%100<< " ";//范围在[0,100)的随机数
}
return 0;
}
插入随机种子后,多次运行代码,随机数的结果不同。
为了方便使用,可以使用宏定义:
#include <iostream>
#include <cstdlib>
#include <ctime>
#define random(x) rand()%(x)
using namespace std;
int main()
{
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 10; i++)
{
cout << random(100) << " ";
}
return 0;
}
Random库
包括:
- 随机数引擎类(random-number engines)
- 随机数分布类(random-number distribution)
- 二者一般配合使用。
1.引擎和分布
①随机数引擎类
- 被称为“原始随机数发生器”,它以均匀的概率生成某一类型的随机数
- 但无法指定随机数的范围、概率等信息,通常不会被单独使用。
②随机数分布类
- 需要配合随机数引擎类才能运行
- 利用随机数引擎生成符合条件的随机数,例如某一区间范围、某一分布概率的随机数。
③随机数类常用的主要有以下四个:
- default_random_engine:随机非负数(不建议单独使用);
- uniform_int_distribution:指定范围的随机非负数;
- uniform_real_distribution:指定范围的随机实数;
- bernoulli_distribution:指定概率的随机布尔值。
2.参考几个实例:
①default_random_engine
- 是一个随机数引擎类。
- 调用运算符无参返回一个随机的 unsigned 类型的值。
#include <iostream>
#include <random>
using namespace std;
int main( )
{
default_random_engine e; // 生成随机无符号数
for(int i=0; i<10; ++i)
cout<<e( )<<endl; // e() “调用”对象来生成下一个随机数
return 0;
}
②uniform_int_distribution
- 是一个随机数分布类,也是个模板类
- 模板参数为生成随机数的类型(int、unsigned、short、unsigned short、long、unsigned long、long long、unsigned long long)。
- 它的构造函数接受两个值,表示随机数的分布范围(闭区间)。
//生成 [0,9]均匀分布的随机数
uniform_int_distribution<unsigned> u(0,9);
default_random_engine e; // 生成无符号随机整数
for (size_t i =0;i<10; i++)
// 将 u 作为随机数源
// 每个调用返回在指定范围内并服从均匀分布的值
cout<<u(e)<<" ";
cout<< endl;
③uniform_real_distribution
- 是一个随机数分布类,它也是模板类
- 参数表示随机数类型(可选类型为 float、double、long double)
#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;
}
④bernoulli_distribution
- 是一个分布类,但它不是模板类。
- 它的构造函数只有一个参数,表示该类返回 true 的概率,该参数默认为 0.5 ,即返回 true 和 false 的概率相等。
#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;
}
3.“固定”的随机
随机数发生器在默认情况下,对于一个给定的发生器,每次运行程序它都会返回相同的随机结果。
- 随机结果不变便于调试,但也不应该忽视这一问题。
通俗讲,就是如果我设置了个函数output_random()输出5个0到9之间的随机数。
- 每次调用output_random()时,输出的结果是一样的。
- 这并不满足我希望每次都有新随机的需求
因此应该将他们定义为static 的,从而每次调用都生成新的数:
static default_random_engine e;
static uniform_int_distribution<unsigned > u(0,9);
或者,在不需要调试确认后,加入随机种子:
default_random_engine e;
e.seed(13);
或者加个时间种子:
default_random_engine e1(time(0));
C++ 11 还规定了可以生成 20 种不同的分布类型,有具体需求时可以参考 C++ Primer 781页或:http://www.cplusplus.com/reference/random/
参考文献1
参考文献2
参考文献3