# 线性同余法
unsigned int PRNG() // pseudo-random number generator
{
static unsigned int seed{5323};
seed = 8253729 * seed + 2396403;
return seed % 32768;
}
1
2
3
4
5
6
2
3
4
5
6
原理大致如上。这样简单的随机数不够"好"。
# C 标准库中的随机数生成
原理就是线性同余法,不同编译器实现略有不同,且大多有缺陷。仅供学习使用。
#include <cstdlib> // for std::rand() and std::srand()
#include <ctime> // for std::time()
void PrintNumbersWithRand()
{
std::srand(static_cast<unsigned int>(std::time(nullptr)));
// 因为某些编译器中rand算法的缺陷,导致第一个随机数大概率相同,所以这里先调用一次去掉第一个
std::rand();
// 打印 100 个随机数
for (int count{1}; count <= 100; ++count)
{
std::cout << std::rand() << '\t';
if (count % 5 == 0)
std::cout << '\n';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 一个好的伪随机数生成器(PRNG)的标准
- 应该以大致相同的概率生成每个数字(生成六个数字5,6,7,8,9的概率大致相等),即数字分布均匀性。
- 生成序列中的下一个数字应该是不可预测。(num = num + 1)
- 生成的数字序列应该有良好的空间分布(生成0-9之间的随机数,不能只生成5,6,7,8,9,生成的数落在大,中,小范围内的概率也应大致相当),即空间分布均匀性。
- 所有的PRNG都有周期性。通常,周期越大越好。
# 更好的随机数生成器
使用梅森旋转演算法(Mersenne Twister)。在C++11中引入。
#include <iostream>
#include <random> // for std::mt19937
#include <ctime> // for std::time
int main()
{
// 初始化 mersenne twister,将时间作为 seed。
std::mt19937 mersenne{ static_cast<std::mt19937::result_type>(std::time(nullptr)) };
// 生成 1-6 之间随机整数的PRNG
std::uniform_int_distribution die{ 1, 6 }; // C++17
// std::uniform_int_distribution<> die{ 1, 6 }; // C++11
for (int count{ 1 }; count <= 48; ++count)
{
std::cout << die(mersenne) << '\t';
if (count % 6 == 0)
std::cout << '\n';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Effolkronium’s random library.
一个随机数库(纯头文件)。提供了便于使用的API。
#include <iostream>
#include "random.hpp"
// get base random alias which is auto seeded and has static API and internal state
using Random = effolkronium::random_static;
int main()
{
std::cout << Random::get(1, 6) << '\n';
std::cout << Random::get(1, 10) << '\n';
// decltype(val) is long double
auto val = Random::get(1.l, -1.l)
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
← C语言 C/C++ 文件 IO →