blueyi's notes

Follow Excellence,Success will chase you!

0%

C++随机数类random的使用

C++中生成随机数即可以使用C语言中的rand和srand的方式,也可以使用C++11中的random类。

cstdlib中伪随机数

C语言中通过函数randsrand来产生伪随机数,这两个函数包含在头文件cstdlib中,其中srand用来产生设置随机数种子,rand每次返回一个当前的种子对应的随机数,这两个函数的声明如下:

1
2
void srand(unsigned seed);
int rand(void);

这两个函数的原型形如:

1
2
3
4
5
6
7
8
9
10
11
12
unsigned long int next = 1;
/* rand: return pseudo-random integer on 0..32767 */
int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
/* srand: set seed for rand() */
void srand(unsigned int seed)
{
next = seed;
}

显然rand只能生成整数,需要小数时,只需要跟一个浮点数进行除法即可
一个生成[1, 15]的随机数例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <cstdlib>
#include <ctime>

//random num range is min to max, template function
template <typename T> T cRandom(int min, int max)
{
return (min + static_cast<T>(max * rand() / static_cast<T>(RAND_MAX + 1)));
}

int main(void)
{
srand((unsigned)time(NULL));
//生成10个整数
std::cout << "int: " << std::endl;
for (int i = 0; i < 10; ++i) {
std::cout << cRandom<int>(1, 15) << " ";
}
std::cout << std::endl;
//生成10个小数
std::cout << "double: " << std::endl;
for (int i = 0; i < 10; ++i) {
std::cout << cRandom<double>(1, 15) << " ";
}
std::cout << std::endl;
return 0;
}

生成指定范围的随机数表达式:
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

C++11中的random类

random类是C++11中增加的类,该类可以用于生成随机数,具有C语言中rand生成伪随机数的功能,但其功能更强大。原生支持生成浮点数,及分布类。

随机数发生器主要由分布对象和随机数引擎对象组成。其中随机数引擎用于根据随机数种子来产生随机数,分布对象对产生的随机数根据需求进行分布。
random中定义了多种随机数引擎及分布类型,常用的引擎是默认伪随机数引擎类default_random_engine,常用的分布类有产生整型分布的uniform_int_distribution,产生浮点型的分布uniform_real_distribution

举例

该程序输出15个double类型的随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <random>
#include <iostream>
#include <ctime>

//该函数接受三个参数分别指定随机数范围和种子,返回double
double random_unint(unsigned int min, unsigned int max, unsigned int seed = 0)
{
static std::default_random_engine e(seed);
static std::uniform_real_distribution<double> u(min, max);
return u(e);
}

int main(void)
{
for (int i = 0; i < 15; ++i) {
std::cout << random_unint(0, 15, time(NULL)) << " ";
}
std::cout << std::endl;
return 0;
}

需要注意

1.一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为static的,否则每次调用函数都会生成相同的序列。也就是说定义成static后每次调用还是之前那个发生器,第一次调用产生一批随机数,再次调用将产生接下来的随机数,否则每次调用产生的都是最前面的那些随机数。

2.依然需要使用time来做为种子产生每个不同时刻都不同的随机序列,但由于time默认返回的是以秒计的时间,所以有可能多次使用的都是相同的种子。

伪随机数引擎

1.随机数引擎支持的操作如下:

  • Engine e; //默认构造函数,使用该引擎类型的默认种子
  • Engine e(s); //使用整型s做为种子
  • e.seed(s); //使用整型s重置引擎状态
  • e.min(); //返回此引擎所能生成的最小和最大值
  • e.max();
  • Engine::result_type //此引擎生成的类型(unsigned)
  • e.discard(u); //将引擎推进u步,u为unsigned long long类型

2.随机数引擎使用

1
2
std::default_random_engine e;   //生成随机的无符号数
std::cout << e(); //通过()调用对象生成下一个随机数并输出

分布

1.分布类型有很多种,常用的有返回整型的uniform_int_distribution和返回浮点型的uniform_real_distribution
2.分布支持的操作

  • Dist d; //默认构造函数
  • Dist d(min, max); //为d指定范围
  • d(e) //e是一个随机数引擎对象
  • d.min() //返回d(e)所能生成的最小值和最大值
  • d.max()
  • d.reset(); //重置d的状态,使得随后对d的使用不依赖于d已经生成的值

Welcome to my other publishing channels