mt19937
mt19937
wiki 说明
mt19937
是一个随机数生成器类,效用同 rand()
,随机数的范围同 unsigned int
类型的取值范围。
其优点是随机数质量高(一个表现为,出现循环的周期更长;其他方面也都至少不逊于 rand()
),且速度比 rand()
快很多。使用时需要 #include<random>
。
mt19937
基于 32 位梅森缠绕器,由松本与西村设计于 1998 年,使用时用其定义一个随机数生成器即可:std::mt19937 myrand(seed)
,seed
可不填,不填 seed
则会使用默认随机种子。
mt19937
重载了 operator()
,需要生成随机数时调用 myrand()
即可返回一个随机数。
另一个类似的生成器是 mt19937_64
,基于 64 位梅森缠绕器,由松本与西村设计于 2000 年,使用方式同 mt19937
,但随机数范围扩大到了 unsigned long long
类型的取值范围。
random_device
random_device
是一个基于硬件的均匀分布随机数生成器,在熵池耗尽 前可以高速生成随机数。该类在 C++11
定义,需要 random
头文件。由于熵池耗尽后性能急剧下降,所以建议用此方法生成 mt19937
等伪随机数的种子,而不是直接生成。
代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <bits/stdc++.h>
using namespace std;
int main()
{
random_device rd;
mt19937 rand1_32(time(nullptr));
mt19937 rand2_32(rd());
// [0, 2^32 - 1 = 4294967295 ≈ 4e9]
mt19937_64 rand1_64(time(nullptr));
mt19937_64 rand2_64(rd());
// [0, 2^64 - 1 = 18446744073709551615 ≈ 1.8e19]
cout << rand1_32() << endl
<< rand2_32() << endl
<< rand1_64() << endl
<< rand2_64() << endl;
return 0;
}
常用成员函数
- 构造函数:
mt19937()
:默认构造函数,使用默认的种子初始化随机数引擎。mt19937(unsigned int seed)
:使用指定的种子初始化随机数引擎。
- 种子操作函数:
seed()
:设置种子值为默认值。seed(unsigned int seed)
:设置新的种子值。
- 随机数生成函数:
operator()
:生成一个 32 位的随机整数。
- 辅助函数:
discard(unsigned long long z)
:等同于执行z次operator(),以丢弃z次生成的随机数。min()
:获取可生成的最小随机数值。max()
:获取可生成的最大随机数值。
在随机打乱数组中的应用
通常情况下我们使用 STL 库中的 std::random_shuffle(first, last)
函数来打乱一个数组。但是此调用的是 rand()
函数作为随机函数,这受 srand()
种子函数的支配。
于是我们可以使用 std::shuffle(first, last, myrand)
函数,第三个参数应当传入一个产生随机数的函数。
1
2
3
4
5
6
7
8
9
10
11
12
#include <bits/stdc++.h>
using namespace std;
int main()
{
random_device rd;
mt19937 rnd(rd());
vector<int> v = {0, 1, 2, 3, 4, 5};
shuffle(v.begin(), v.end(), rnd);
for(auto i : v)
cout << i << " ";
return 0;
}
本文由作者按照 CC BY 4.0 进行授权