怪不得说C++难学,这里连个随机数生成器都要折腾好久,要是换做C#,一个Random()方法就解决了。
话说虽然C++继承了C语言的Rand()函数,但我想说的是,用它生成的随机数的概率精度是真的低。
不过到了C++11后,标准库新增了一个新的随机数生产方法,mt19937,下面就来大略的分析和简练一下这个方法。

MT19937随机数生成器

1 . mt19937随机数生成器采用的是梅森旋转算法(Mersenne twister)来达到生成随机数,这个算法可以快速产生高质量高精度的32位伪随机数,
2 . 使用该算法生成的随机数不仅质量高,速度也快出其他生成器,
3 . 看名字也知道,它的取值范围是:2^19937-1,也就是19937的2次方减去1,这个数值非常大,以至于它远远超出了常规计算机和编程语言能够表示的整数范围。实际上,这个数字的位数将非常惊人,远远超出了任何标准整数类型的范围,所以在编程时,已经没有弄清它的取值范围的必要了。

4 . 在C++中,可以通过#include <random>来引入该标准库。
5 . 为了保证每次运行时输出的随机数不一样,我们需要使用time(0),它表示用当前时间来初始化随机数生成器的种子,说直白点就是:只要当前时间有变化,生成的随机数序列就会不同,这样可以尽量避免每次运行时的生成重复的随机数。这个方法来源于<time.h>标准库,所以需要先引入才能使用。
6 . 在C++中,默认情况下,mt19937随机数生成器会生成一个32位的无符号整数,最大值是 2^32 - 1,也就是:4294967295。

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <random>
#include <time.h>

using namespace std;
int main()
{
mt19937 RandomInt(time(0));
cout << RandomInt() << endl;

}

7 . 所以,如果将上述代码放到循环可以看到,它的取值范围为:(0 ~ 4294967295)

指定分布随机数范围

C++ 标准库 提供了一个模块类,该模块类用于生成在指定范围内均匀分布的随机整数

std::uniform_int_distribution<int> Name(start, end);

  • Name:模块类名称
  • start:区间一
  • end:区间二

1 . 将得到的随机数放到这个指定好整数范围模块内,即可得到一个新的范围内的随机数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <random>
#include <time.h>

using namespace std;
int main()
{
// 初始化种子
mt19937 mt19937_RandomInt(time(0));
// 指定随机数分布范围
uniform_int_distribution<int> Distribution_temp(1,10);
// 从指定范围内生成新的随机数
int RandomInt = Distribution_temp(mt19937_RandomInt);
cout << RandomInt << endl;
}

封装成自定义函数库

1 . 为了以后开发方便调用随机数生成器,我们可以将写好的生成器封装成一个头文件,后续调用更方便。
2 . 只需要写一个可传两个参数的方法即可。

头文件:almadef.h

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
28
29
#include <random>
#include <iostream>
#include <time.h>

using namespace std;

namespace Basefunction

{
int RandomIntNum(int value, int value2)
{
// 初始化种子
mt19937 mt19937_RandomInt(time(0));
// 指定随机数分布范围
uniform_int_distribution<int> Distribution_temp(value, value2);
// 从指定范围内生成新的随机数
int RandomInt = Distribution_temp(mt19937_RandomInt);
// 返回给源文件
return RandomInt;

// string Randintnum_temp_to_string = to_string(Randintnum_temp);
// char splitintnum = Randintnum_temp_to_string.back();
// // cout << splitintnum << endl;
// int Randintnum_temp_to_int = splitintnum - '0';
// // return Randintnum_temp_to_int;
// return Randintnum_temp_to_int;

}
};

源文件:index.cpp

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include "almadef.h"

using namespace std;
using namespace Basefunction;
int main()
{
int a = RandomIntNum(5, 15);
cout << "生成的随机数为:" << a << endl;
}

3 . 可以看到,在源文件中调用自定义好的随机数生成器,会方便不少,变得更加灵活好用了。
4 . 当然,后续我希望我能自定义更多函数方法库,在自定义中不断学习和使得开发更加高效。