C++时间和随机数相关库
约 2667 个字 346 行代码 1 张图片 预计阅读时间 13 分钟
基础:编译时有理数算术(<ratio>
)
编译时有理数与ratio
在接下来介绍ratio
类之前,先了解何为「编译时有理数」
「编译时有理数」指的是其值在程序编译期间就已经确定并且可以进行计算的有理数(分数)
在C++中,std::ratio
就是用来表示这种编译时有理数的工具。关键点在于:
- 模板定义:
std::ratio<Num, Den>
使用模板参数Num
(分子)和Den
(分母)来定义一个分数。这些参数必须是编译时就能确定的整数常量 - 类型表示:
std::ratio<1, 1000>
本身是一个类型,而不是一个运行时变量。它的值(1/1000)是这个类型的一个属性 - 编译期计算:所有涉及
std::ratio
的算术(如std::ratio_add
)和比较(如 std::ratio_less
)操作都在编译时完成。编译器会计算出结果,并生成一个新的 std::ratio
类型 - 无运行时开销:由于计算在编译时完成,直接操作
std::ratio
类型本身(例如,确定std::milli::num
和std::milli::den
)在运行时没有计算开销 - 用于元编程和常量:它们非常适合用于模板元编程和定义固定的、在编译时就需要确定的常量比例,就像
<chrono>
库中定义时间单位(毫秒、微秒等)那样
简单来说,它是一种在编译代码时由编译器处理和计算的分数表示方法,而不是等到程序运行时再计算
基本介绍
<chrono>
库广泛使用<ratio>
库来表示编译时的分数,这对于定义时间单位(例如秒、毫秒)至关重要
std::ratio
是一个模板类,用于表示编译时的有理数 Num / Den
C++ |
---|
| template <std::intmax_t Num, std::intmax_t Den = 1>
class ratio;
|
其中 Num
是分子(numerator),Den
是分母(denominator),分母必须非零,且分数会自动约简
成员变量
成员 | 类型 | 描述 |
num | std::intmax_t | 约简后的分子 |
den | std::intmax_t | 约简后的分母 |
关于类型的定义,可以在C语言头文件<stdint.h>
中查看
预定义Ratio类型
标准库提供了一些常用的SI单位前缀的 ratio
类型别名,例如(由小到大) std::atto
、std::femto
、std::pico
、std::nano
、std::micro
、std::milli
、std::centi
、std::deci
、std::deca
、std::hecto
、std::kilo
、std::mega
、std::giga
、std::tera
、std::peta
和 std::exa
单位对照表如下:

Ratio算术
<ratio>
提供了编译时算术运算的类型别名,包括如下:
std::ratio_add
(加法) std::ratio_subtract
(减法) std::ratio_multiply
(乘法) std::ratio_divide
(除法)
Ratio比较
<ratio>
提供了编译时比较运算的类型别名,包括 1. std::ratio_equal
(等于) 2. std::ratio_not_equal
(不等于) 3. std::ratio_less
(小于) 4. std::ratio_less_equal
(小于等于) 5. std::ratio_greater
(大于) 6. std::ratio_greater_equal
(大于等于)
示例代码
C++ |
---|
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 <ratio>
int main()
{
// 定义ratio类型
using one_third = std::ratio<1, 3>;
using two_fourths = std::ratio<2, 4>; // 会被约简为1/2
// 访问num和den
std::cout << "one_third: " << one_third::num << "/" << one_third::den << std::endl;
std::cout << "two_fourths: " << two_fourths::num << "/" << two_fourths::den << std::endl;
// Ratio算术
using sum = std::ratio_add<one_third, two_fourths>; // 1/3 + 1/2 = 5/6
std::cout << "Sum: " << sum::num << "/" << sum::den << std::endl;
using product = std::ratio_multiply<one_third, std::kilo>; // (1/3) * (1000/1) = 1000/3
std::cout << "Product: " << product::num << "/" << product::den << std::endl;
// Ratio比较
// 比较1/3和1/2
bool less = std::ratio_less<one_third, two_fourths>::value;
std::cout << "Is 1/3 less than 1/2? " << std::boolalpha << less << std::endl; // 输出rue
return 0;
}
|
时间工具(<chrono>
)
<chrono>
库提供了处理时间的三大核心组件:时钟(Clocks)、时间段(Durations)和时间点(Time points)
时钟(Clocks)
时钟提供了对当前时间点的访问,C++标准库定义了三种主要时钟:
std::chrono::system_clock
代表系统范围的实时时钟(挂钟时间),它是唯一可以映射到C风格time_t
的时钟,但不一定是单调递增的 std::chrono::steady_clock
代表单调递增的时钟,时间点永不减少,最适合用于测量时间间隔 std::chrono::high_resolution_clock
提供具有最小可用时钟周期的时钟,通常是 system_clock
或steady_clock
的别名
单调递增时钟与非单调递增时钟
- 单调递增的时钟就像一个秒表计数器**:它只管从某个起点开始一直往前数时间,不受外界干扰,非常适合测量经过了多长时间
- 不单调递增的时钟就像电脑右下角的系统时间**:它显示的是当前的“挂钟时间”,这个时间可能会因为人为修改、网络同步、夏令时等原因向前或向后跳变
system_clock
成员
now() noexcept
:(静态)返回表示当前时间的time_point
to_time_t(const time_point& t) noexcept
:(静态)将time_point
转换为 std::time_t
from_time_t(std::time_t t) noexcept
:(静态)将std::time_t
转换为 time_point
is_steady
:(静态)false
,表示时钟不是单调递增的
steady_clock
成员
now() noexcept
:(静态)返回表示当前时间的time_point
is_steady
:(静态)true
,表示时钟是单调递增的
high_resolution_clock
成员
now() noexcept
:(静态)返回表示当前时间的time_point
is_steady
:(静态)取决于它所别名的时钟
示例代码
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39 | #include <iostream>
#include <chrono>
#include <ctime> // for std::time_t, std::gmtime, std::put_time
#include <iomanip> // for std::put_time
#include <thread> // for std::this_thread::sleep_for
int main()
{
// --- system_clock ---
std::chrono::system_clock::time_point sys_now = std::chrono::system_clock::now();
std::time_t sys_now_c = std::chrono::system_clock::to_time_t(sys_now);
// 将 time_t 转换为 UTC 时间结构
std::tm sys_now_tm = *std::gmtime(&sys_now_c);
std::cout << "System clock time: " << std::put_time(&sys_now_tm, "%Y-%m-%d %H:%M:%S UTC") << std::endl;
// --- steady_clock ---
std::chrono::steady_clock::time_point steady_start = std::chrono::steady_clock::now();
std::cout << "Starting steady clock measurement..." << std::endl;
// 模拟一些工作
// 线程睡眠
std::this_thread::sleep_for(std::chrono::milliseconds(150));
std::chrono::steady_clock::time_point steady_end = std::chrono::steady_clock::now();
// 计算时间差 (duration)
std::chrono::duration<double, std::milli> elapsed_ms = steady_end - steady_start;
std::cout << "Elapsed time (steady_clock): " << elapsed_ms.count() << " ms" << std::endl;
// --- high_resolution_clock ---
std::chrono::high_resolution_clock::time_point high_res_now = std::chrono::high_resolution_clock::now();
// high_resolution_clock通常没有直接转换为time_t的方法,因为它可能是 steady_clock
// 但我们可以获取自纪元以来的时间
auto high_res_epoch = high_res_now.time_since_epoch();
// 将其转换为纳秒
long long ns = std::chrono::duration_cast<std::chrono::nanoseconds>(high_res_epoch).count();
std::cout << "High resolution clock (nanoseconds since epoch): " << ns << std::endl;
std::cout << "High resolution clock is steady: " << std::boolalpha << std::chrono::high_resolution_clock::is_steady << std::endl;
return 0;
}
|
put_time
函数
std::put_time
是C++标准库<iomanip>
中的一个输出流操纵符(output stream manipulator)
它的作用是:
- 接收一个指向
std::tm
结构体的指针:std::tm
结构体包含了年、月、日、时、分、秒等日历时间信息 - 接收一个格式化字符串:这个字符串指定了如何将
std::tm
中的时间信息转换成文本表示。它使用与C语言函数strftime
相同的格式代码(例如%Y
代表四位数年份,%m
代表月份,%d
代表日期,%H
代表小时(24小时制),%M
代表分钟,%S
代表秒) - 格式化时间:根据提供的格式字符串,将
std::tm
结构体中的时间信息格式化成一个字符串 - 插入到输出流:将格式化后的时间字符串插入到它所应用的输出流中(例如
std::cout
)
时间段(Durations)
std::chrono::duration
表示一个时间间隔,由一个计数值和一个表示计数的单位(例如秒、毫秒)的ratio
组成
C++ |
---|
| template <class Rep, class Period = std::ratio<1>>
class duration;
|
其中 Rep
是用于表示计数值的算术类型(例如 int
、long
、double
),Period
是一个std::ratio
类型,表示每个计数值代表的秒数(例如std::milli
表示每个计数值是\(\frac{1}{1000}\)秒) 成员函数
成员 | 描述 |
count() | 返回duration 的计数值 |
zero() | (静态 C++11/14)返回零长度的duration |
min() | (静态 C++11/14)返回可表示的最小duration |
max() | (静态 C++11/14)返回可表示的最大duration |
预定义Duration类型
标准库提供了常用的duration
类型别名,包括:
std::chrono::nanoseconds
std::chrono::microseconds
std::chrono::milliseconds
std::chrono::seconds
std::chrono::minutes
std::chrono::hours
std::chrono::days
(C++20) std::chrono::weeks
(C++20) std::chrono::months
(C++20) std::chrono::years
(C++20)
Duration运算
Duration支持算术运算(+
、-
、*
(与数值)、/
(与数值或duration
)、%
(与数值或duration
)和比较运算(==
、!=
、<
、<=
、>
、>=
),比较会自动处理不同单位的转换
duration
类型转换
std::chrono::duration_cast
用于在不同类型的duration
之间进行显式转换,转换可能会截断(不会四舍五入)
C++ |
---|
| template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
|
示例代码
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | #include <iostream>
#include <chrono>
int main()
{
// 创建 durations
std::chrono::seconds s(5); // 5 秒
std::chrono::milliseconds ms = std::chrono::milliseconds(1500); // 1500 毫秒
std::chrono::duration<double, std::ratio<1, 3>> third_of_sec(1.0); // 1/3 秒
// 访问count()
std::cout << "Seconds count: " << s.count() << std::endl;
std::cout << "Milliseconds count: " << ms.count() << std::endl;
std::cout << "Third of second count: " << third_of_sec.count() << std::endl;
// Duration 算术
auto total_ms = s + ms; // 5s + 1500ms = 6500ms
// 注意:结果类型是两个操作数周期的最大公约数,表示类型是std::common_type
// 在这里,结果类型可能是milliseconds或更精细的类型
// 为了明确,我们通常使用duration_cast
std::chrono::milliseconds total_ms_casted = std::chrono::duration_cast<std::chrono::milliseconds>(s) + ms;
std::cout << "Total milliseconds: " << total_ms_casted.count() << std::endl;
auto half_s = s / 2; // 结果是2秒 (整数除法)
std::cout << "Half of 5 seconds (integer division): " << half_s.count() << std::endl;
std::chrono::duration<double> s_double = s; // 隐式转换为double类型的秒
auto precise_half_s = s_double / 2.0; // 结果是2.5秒
std::cout << "Half of 5 seconds (double division): " << precise_half_s.count() << std::endl;
// Duration比较
if (ms < s) {
std::cout << "1500 ms is less than 5 s" << std::endl;
}
// duration_cast
std::chrono::seconds ms_to_s = std::chrono::duration_cast<std::chrono::seconds>(ms); // 1500ms -> 1s (截断)
std::cout << "1500 ms casted to seconds: " << ms_to_s.count() << std::endl;
std::chrono::microseconds s_to_us = std::chrono::duration_cast<std::chrono::microseconds>(s); // 5s -> 5,000,000 us
std::cout << "5 s casted to microseconds: " << s_to_us.count() << std::endl;
// C++14 字面量 (需要 using namespace std::chrono_literals)
using namespace std::chrono_literals;
auto literal_duration = 1h + 30min + 5s + 100ms + 20us + 300ns;
std::cout << "Literal duration in nanoseconds: "
<< std::chrono::duration_cast<std::chrono::nanoseconds>(literal_duration).count() << std::endl;
return 0;
}
|
时间点(Time Points)
std::chrono::time_point
表示一个特定的时间点,它关联到一个时钟,并表示为从该时钟纪元(epoch)开始的一段 duration
C++ |
---|
| template <class Clock, class Duration = typename Clock::duration>
class time_point;
|
其中 Clock
是关联的时钟类型(例如 system_clock
、steady_clock
),Duration
是用于表示从纪元开始的时间间隔的 duration
类型(默认为关联时钟的 duration
类型) 成员函数
成员 | 描述 |
time_since_epoch() | 返回从关联时钟的纪元开始到此时间点的 duration |
min() | (静态 C++11/14)返回可表示的最早时间点 |
max() | (静态 C++11/14)返回可表示的最晚时间点 |
Time Point 运算
Time Point 支持与 duration
的加减运算(time_point + duration
、time_point - duration
),以及相同类型时钟的 time_point
之间的减法(time_point - time_point
,结果为 duration
)和比较运算(==
、!=
、<
、<=
、>
、>=
)
std::chrono::time_point_cast
std::chrono::time_point_cast
用于在具有相同关联时钟但不同 duration
类型的 time_point
之间进行显式转换
C++ |
---|
| template <class ToDuration, class Clock, class Duration>
constexpr std::chrono::time_point<Clock, ToDuration>
time_point_cast(const std::chrono::time_point<Clock, Duration>& tp);
|
代码示例
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 | #include <iostream>
#include <chrono>
#include <thread> // for sleep_for
int main() {
using namespace std::chrono; // 方便使用 chrono 下的类型
// 获取当前时间点
system_clock::time_point tp_sys_now = system_clock::now();
steady_clock::time_point tp_steady_now = steady_clock::now();
// 获取自纪元以来的时间
auto sys_epoch_duration = tp_sys_now.time_since_epoch();
auto steady_epoch_duration = tp_steady_now.time_since_epoch();
// 转换为特定单位
long long sys_ms_count = duration_cast<milliseconds>(sys_epoch_duration).count();
long long steady_ns_count = duration_cast<nanoseconds>(steady_epoch_duration).count();
std::cout << "System clock time_point (ms since epoch): " << sys_ms_count << std::endl;
std::cout << "Steady clock time_point (ns since epoch): " << steady_ns_count << std::endl;
// Time point 算术
system_clock::time_point tp_sys_later = tp_sys_now + minutes(10); // 10 分钟后的时间点
auto diff_duration = tp_sys_later - tp_sys_now; // 计算差值,结果是 duration
std::cout << "Difference is: " << duration_cast<seconds>(diff_duration).count() << " seconds" << std::endl;
// Time point 比较
steady_clock::time_point tp_steady_start = steady_clock::now();
std::this_thread::sleep_for(50ms); // 暂停 50 毫秒
steady_clock::time_point tp_steady_end = steady_clock::now();
if (tp_steady_end > tp_steady_start) {
std::cout << "Steady clock time point increased." << std::endl;
}
// time_point_cast
// 将 system_clock 的 time_point 精度改为秒
time_point<system_clock, seconds> tp_sys_seconds = time_point_cast<seconds>(tp_sys_now);
// 再次获取自纪元以来的时间 (以秒为单位)
std::cout << "System clock time_point (seconds since epoch): "
<< tp_sys_seconds.time_since_epoch().count() << std::endl;
return 0;
}
|
C++14 时间字面量
C++14 引入了方便的字面量来创建 duration
对象,例如 h
(小时)、min
(分钟)、s
(秒)、ms
(毫秒)、us
(微秒)和 ns
(纳秒),使用时需要 using namespace std::chrono_literals;
或 using namespace std::literals::chrono_literals;
C++ |
---|
| using namespace std::chrono_literals;
auto my_duration = 2h + 45min + 10s;
std::cout << "Duration in seconds: " << my_duration.count() << std::endl; // 输出 9910
|
随机数生成(<random>
)
<random>
库提供了一套用于生成伪随机数的组件,主要包括引擎(Engines,生成原始伪随机整数序列)、分布(Distributions,将引擎序列转换为特定统计属性的随机数)和工具(Utilities,例如种子生成器)
随机数引擎(Engines)
引擎是函数对象,调用 operator()
会返回序列中的下一个伪随机数
常用引擎
常用的引擎包括 linear_congruential_engine
(线性同余生成器,速度快但随机性一般,常用别名 minstd_rand0
、minstd_rand
)、mersenne_twister_engine
(梅森旋转算法,高质量随机数,常用别名 mt19937
、mt19937_64
)和 subtract_with_carry_engine
(带借位减法生成器,常用别名 ranlux24_base
、ranlux48_base
)
引擎通用成员
引擎通常包含接受种子值进行初始化的构造函数、生成下一个随机数的 operator()
、使用新种子重新初始化的 seed()
方法、返回生成范围的静态 min()
和 max()
方法,以及跳过序列中若干数字的 discard(n)
方法
std::random_device
std::random_device
是一个特殊的随机数生成器,它尝试从硬件(或其他非确定性来源)获取熵来生成随机数,通常用于为伪随机数引擎提供种子,其 operator()
返回一个随机数,entropy()
返回熵的估计值(位数,若为零则可能使用伪随机数引擎作为后备)
代码示例(引擎和 seeding)
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39
40
41 | #include <iostream>
#include <random>
#include <vector>
#include <numeric> // for std::iota
#include <algorithm> // for std::shuffle
int main() {
// --- 使用 random_device 获取种子 ---
std::random_device rd; // 获取一个随机设备
unsigned int seed = rd(); // 用它生成一个种子
std::cout << "Seed generated by random_device: " << seed << std::endl;
std::cout << "random_device entropy: " << rd.entropy() << std::endl;
// --- 创建和使用引擎 ---
// 使用 random_device 的种子初始化梅森旋转引擎
std::mt19937 engine(seed);
std::cout << "Generating 5 numbers using mt19937:" << std::endl;
for (int i = 0; i < 5; ++i) {
// 调用 operator() 生成原始随机整数
std::cout << engine() << " ";
}
std::cout << std::endl;
// 引擎的范围
std::cout << "mt19937 min: " << engine.min() << std::endl;
std::cout << "mt19937 max: " << engine.max() << std::endl;
// discard
engine.discard(10); // 跳过 10 个数
std::cout << "Next number after discarding 10: " << engine() << std::endl;
// 重新 seeding
engine.seed(12345); // 使用固定种子
std::cout << "First number after seeding with 12345: " << engine() << std::endl;
engine.seed(12345); // 再次使用相同种子
std::cout << "First number after seeding with 12345 again: " << engine() << std::endl; // 输出应与上一个相同
return 0;
}
|
随机数分布(Distributions)
分布是函数对象,它接受一个引擎作为输入,并使用引擎生成的原始随机数来产生符合特定概率分布的随机数
通用成员
分布通常包含接受分布参数(例如范围、均值、标准差等)的构造函数、接受引擎引用并返回符合分布随机数的 operator()
、重置分布内部状态的 reset()
方法、获取或设置分布参数对象的 param()
方法、返回分布可能生成范围的 min()
和 max()
方法,以及访问特定分布参数的函数(例如 mean()
、stddev()
、p()
、lambda()
等)
常用分布类别
常用的分布类别包括:
- 均匀分布(Uniform Distributions):例如
std::uniform_int_distribution
(整数)和 std::uniform_real_distribution
(浮点数) - 伯努利分布(Bernoulli Distributions):例如
std::bernoulli_distribution
、std::binomial_distribution
、std::negative_binomial_distribution
和 std::geometric_distribution
- 泊松分布(Poisson Distributions):例如
std::poisson_distribution
、std::exponential_distribution
、std::gamma_distribution
、std::weibull_distribution
和 std::extreme_value_distribution
- 正态分布(Normal Distributions):例如
std::normal_distribution
、std::lognormal_distribution
、std::chi_squared_distribution
、std::cauchy_distribution
、std::fisher_f_distribution
和 std::student_t_distribution
- 抽样分布(Sampling Distributions):例如
std::discrete_distribution
、std::piecewise_constant_distribution
和 std::piecewise_linear_distribution
代码示例(引擎与分布结合)
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 | #include <iostream>
#include <random>
#include <vector>
#include <map>
#include <iomanip> // for std::fixed, std::setprecision
int main() {
// --- 设置引擎 ---
std::random_device rd;
std::mt19937 gen(rd()); // 使用 random_device 播种
// --- 均匀分布 ---
std::uniform_int_distribution<> distrib_int(1, 6); // [1, 6] 整数
std::uniform_real_distribution<> distrib_real(0.0, 1.0); // [0.0, 1.0) 浮点数
std::cout << "Rolling a die 5 times: ";
for (int i = 0; i < 5; ++i) {
std::cout << distrib_int(gen) << " "; // 使用引擎生成符合分布的数
}
std::cout << std::endl;
std::cout << "Generating 5 random doubles [0.0, 1.0): ";
std::cout << std::fixed << std::setprecision(4); // 设置输出格式
for (int i = 0; i < 5; ++i) {
std::cout << distrib_real(gen) << " ";
}
std::cout << std::endl;
// --- 正态分布 ---
double mean = 5.0;
double stddev = 2.0;
std::normal_distribution<> distrib_normal(mean, stddev);
std::cout << "Generating 10 numbers from normal distribution (mean=5.0, stddev=2.0):" << std::endl;
std::map<int, int> hist; // 用于统计直方图
for (int i = 0; i < 10000; ++i) {
double num = distrib_normal(gen);
++hist[std::round(num)]; // 四舍五入并计数
}
// 简单打印直方图
for(auto const& [val, count] : hist) {
// 限制输出范围,避免过多输出
if (val >= 0 && val <= 10) {
std::cout << std::setw(2) << val << ": " << std::string(count / 100, '*') << '\n';
}
}
// --- 离散分布 ---
std::vector<double> weights = {10.0, 20.0, 70.0}; // 权重对应索引 0, 1, 2
// 索引 0 的概率是 10/(10+20+70) = 10%
// 索引 1 的概率是 20/(10+20+70) = 20%
// 索引 2 的概率是 70/(10+20+70) = 70%
std::discrete_distribution<> distrib_discrete(weights.begin(), weights.end());
std::cout << "Generating 10 numbers from discrete distribution (weights 10, 20, 70): ";
std::map<int, int> discrete_counts;
for (int i = 0; i < 1000; ++i) {
discrete_counts[distrib_discrete(gen)]++;
}
for(auto const& [val, count] : discrete_counts) {
std::cout << "Index " << val << ": " << count << " times ";
}
std::cout << std::endl;
// 访问分布参数
auto params = distrib_normal.param();
std::cout << "Normal distribution mean: " << params.mean() << ", stddev: " << params.stddev() << std::endl;
return 0;
}
|
随机数工具(Utilities)
<random>
库还提供了一些工具:std::seed_seq
用于从一系列整数生成高质量的种子序列,特别适合初始化需要多个种子值的引擎或多个不同的引擎;std::generate_canonical<RealType, bits>(engine)
用于生成一个 [0, 1)
范围内具有指定位数随机性(精度)的浮点数;std::shuffle(first, last, engine)
用于使用给定的引擎随机打乱指定范围内的元素,是 std::random_shuffle
(C++17 中弃用)的推荐替代品
代码示例(Utilities)
C++ |
---|
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 | #include <iostream>
#include <random>
#include <vector>
#include <numeric> // for std::iota
#include <algorithm> // for std::shuffle, std::copy
#include <iterator> // for std::ostream_iterator
#include <array> // for std::array
int main() {
// --- seed_seq ---
std::seed_seq sseq{1, 2, 3, 4, 5}; // 从整数列表创建 seed_seq
std::array<std::uint32_t, 8> seeds; // 准备接收生成的种子
sseq.generate(seeds.begin(), seeds.end()); // 生成种子序列
std::cout << "Generated seeds using seed_seq: ";
for (std::uint32_t seed : seeds) {
std::cout << seed << " ";
}
std::cout << std::endl;
// 使用 seed_seq 初始化引擎
std::mt19937 engine_from_sseq(sseq);
std::cout << "First number from engine seeded by seed_seq: " << engine_from_sseq() << std::endl;
// --- generate_canonical ---
std::random_device rd_canon;
std::mt19937 gen_canon(rd_canon());
std::cout << "Generating 5 canonical doubles [0, 1): ";
std::cout << std::fixed << std::setprecision(10);
for (int i = 0; i < 5; ++i) {
// 生成具有 64 位随机性的 double
double canonical_rand = std::generate_canonical<double, 64>(gen_canon);
std::cout << canonical_rand << " ";
}
std::cout << std::endl;
// --- shuffle ---
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1); // 用 1, 2, ..., 10 填充向量
std::cout << "Original vector: ";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::random_device rd_shuffle;
std::mt19937 g_shuffle(rd_shuffle());
std::shuffle(v.begin(), v.end(), g_shuffle); // 使用引擎打乱向量
std::cout << "Shuffled vector: ";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
|