目录
①static time_point now() 获取当前时间点
②static time64_t to_time_t(const time_point x);
③time_point from_time_t(time_t x);
2.system_clock:获取时间点(time_point->在system_clock类中),需要转换为time_t才能显示出来
4. high_resolution_clock: 高精度时钟
③了解部分 (适配器的实例化->产生随机数 等效于 直接用内置引擎)
一、时间段
1.表示时间间隔,可以是秒,分钟,小时,微妙,毫秒,纳秒
#include<chrono>
2.创建:
一般使用的时候,不建议用duration类来使用,直接使用别名即可。
using nanoseconds = duration<long long, nano>; //纳秒
using microseconds = duration<long long, micro>; //微妙
using milliseconds = duration<long long, milli>; //毫秒
using seconds = duration<long long>; //秒
using minutes = duration<int, ratio<60>>; //分钟 ->ratio<60>是分子除以分母,本处就是1min
using hours = duration<int, ratio<3600>>; //小时
chrono::duration < long long,ratio<60>> dur;
//相当于创建1min (ratio是一个60/1默认->60s)
chrono::hours h(1); //1h
chrono::minutes m(1); //1min
3.常用的场景:线程的睡眠
#include<thread>
注意:C++中sleep_for是对文本进行相关的重载过了,所以用下面两种方式进行休眠会更加方便。
cout << "延时1秒钟" << endl;
this_thread::sleep_for(chrono::seconds(1)); //延时1描述
cout << "延时3秒钟" << endl;
//直接使用文本重载的形式使用时间,没必要用类去构造函数
this_thread::sleep_for(1s);
cout << "延时500毫秒" << endl;
this_thread::sleep_for(500ms);
//cout << "延时1小时" << endl;
//this_thread::sleep_for(chrono::hours(1));
4.时间段之间的相加减操作
①时间段之间允许直接进行运算符 ,不需要大家做一个转换操作
②//chrono::minutes res2 = h1 - sec1;× 用minute来接收是不被允许的!
/*如何正常接收并转换,见第三部分,时间转换 duration_cast 亦或是采用 chrono::duration<double,ratio(...)>的实例化对象来接收即可!*/
③//count函数可以打印时间间隔多少
//时间段之间允许直接进行运算符 ,不需要大家做一个转换操作
chrono::hours h1(1);
chrono::seconds sec1(100);
chrono::seconds result = h1 - sec1;
//chrono::minutes res2 = h1 - sec1;用minute来接收是不被允许的!!!
/*如何正常接收并转换,见第三部分,时间转换 duration_cast*/
//count函数可以打印时间间隔多少秒
cout <<"s:" << result.count() << endl;
输出:s:3500
二、时钟
#include<chrono>
#include<iomanip> /*put_time*/
#include<thread>
1. 时钟类共用的一些函数
①static time_point now() 获取当前时间点
②static time64_t to_time_t(const time_point x);
//类型转化:至 time_t
③time_point from_time_t(time_t x);
//类型转化:至time_point
2.system_clock:获取时间点(time_point->在system_clock类中),需要转换为time_t才能显示出来
void test_system_clock()
{
//1.获取时间点
chrono::system_clock::time_point result =
chrono::system_clock::now();
//2.获取时间点,转换为可以显示的时间:time_t
time_t m_tm = chrono::system_clock::to_time_t(result);
//time_t : 时间戳 离1970多少秒
//打印法一:转换为正确的时间打印处理,ctime:转换为字符串
cout << ctime(&m_tm) << endl;
//打印法二:利用利用iomanip中put_time函数(参数类型是tm->localtime转换)
std::tm* p = localtime(&m_tm);
cout << "格式化时间:" << put_time(p, "%F %T") << endl;
/*其余的时间格式控制字符串,见cplusplus官网,搜put_time()*/
cout <<"时间段打印时间戳:" << result.time_since_epoch().count() << endl;
chrono::system_clock::time_point end =
chrono::system_clock::now();
auto duration = end-result;
cout << duration.count() << endl;//单位:ns纳秒
}
输出:
Sun Jul 3 07:30:43 2022
格式化时间:2022-07-03 07:30:43
时间段打印时间戳:16568046436160916
53405 //ns
注意:上述时间点(time_point)和时间戳(time_t)的区别与转化。
以及时间点(time_point)的打印需要先调用time_since_epoch()再调动count()
3.steady_clock: 计时 类似秒数
void test_steady_clock()
{
chrono::steady_clock::time_point startTime = chrono::steady_clock::now();
this_thread::sleep_for(1s);
auto endTime = chrono::steady_clock::now();/*直接用auto推断偷懒*/
auto time = endTime - startTime;
cout <<"耗时:" << time.count() <<"ns" << endl;
chrono::duration<double,ratio<1>> sec = endTime - startTime;
cout << "耗时:" << sec.count() << "s" << endl;
}
输出:
耗时:1007550200ns
耗时:1.00755s
注:如何将时间间隔的ns自动转化为s秒。
->chrono::duration<double,ratio<1>> sec =endTime-startTime;
---同理,将ratio<1>改成ratio<60>就是以min作为单位。
4. high_resolution_clock: 高精度时钟
void test_high_resolution_clock()
{
//时间间隔和计算机运行速度有关,和什么精度时钟无关
//只是说高的精度 更贴近实际时间。
auto startTime = chrono::high_resolution_clock::now();
this_thread::sleep_for(1s);
auto endTime =chrono::high_resolution_clock::now();
/*上面这句话等效于:
chrono::high_resolution_clock::time_point endTime =
chrono::high_resolution_clock::now();*/
auto time = endTime - startTime;
cout << "耗时:" << time.count() << "ns" << endl;
chrono::duration<double, ratio<1>> sec = endTime - startTime;
cout << "耗时:" << sec.count() << "s" << endl;
}
输出:
耗时:1006585200ns
耗时:1.00659s
用法基本相同(类似)。
三、时间转化
1.duration_cast:不属于duration 类
浮点时长和整数时长之间可以直接隐式转化,其他情况要使用这个函数做转换
void test_duration_cast()
{
chrono::high_resolution_clock::time_point
start = chrono::high_resolution_clock::now();
this_thread::sleep_for(1s);
auto end= chrono::high_resolution_clock::now();
//当end-start无法赋值的时候,就记得duration_cast即可。
chrono::milliseconds dtime
= chrono::duration_cast<chrono::milliseconds>(end - start);
/*milliseconds->毫秒ms*/
cout << dtime.count()<<"ms" << endl;
//浮点形隐式转换->无需强转(直接隐式转化,end和start均是long长整型)
chrono::duration<double, ratio<1, 1000>> dtime2 = end - start;
cout << dtime2.count() << "ms" << endl;
}
输出:
1007ms
1007.1ms
2.time_point_cast :不属于time_point
(使用情况)存在精度丢失的ratio转换,就必须使用time_point_cast做转换
//辅助函数
template <class Duration>
void print_ms(const chrono::time_point<chrono::high_resolution_clock, Duration> time_point)
{
cout << time_point.time_since_epoch().count()<<"ms" << endl;
}
void test_time_point_cast()
{
using TIMEMS = chrono::time_point<chrono::high_resolution_clock, chrono::milliseconds>;
TIMEMS time_point_sec(6s); //chrono::seconds(6) 替换6s
//秒到毫秒(不存在精度丢失)
TIMEMS time_point_ms(time_point_sec);
print_ms(time_point_ms);
time_point_ms = TIMEMS(6789ms);
using TIMESEC = chrono::time_point<chrono::high_resolution_clock, chrono::seconds>;
//毫秒到秒赋值(会有精度丢失,要用time_point_cast)
TIMESEC time_sec =chrono::time_point_cast<chrono::seconds>(time_point_ms);
//强转到seconds
print_ms(time_sec);
}
输出:
6000ms
6ms
四、种子序列 seed_seq 类似于一种容器
头文件:
#include<random>
#include<functional> //仿函数
类似C语言srand函数 ,用来设置范围
-
size() 检测种子个数
-
generate()函数 (通过内部的算法计算后,填充某个容器)
-
param()函数
#include <iostream> #include <random> #include <functional> #include <array> using namespace std; int main() { seed_seq seed = { 1,3,4,5,6,7,8 }; cout <<"size:" << seed.size() << endl; array<int, 7> data; seed.param(data.begin()); for (auto v : data) { cout << v << "\t"; } cout << endl; //array<int, 7> data2; //seed.generate(data2.begin(), data2.end()); //for (auto v : data2) //{ // cout << v << "\t"; //} cout << endl; return 0; }
输出:
size:7
1 3 4 5 6 7 8
五、 随机数&引擎适配器
1. 四种引擎适配器:
shuffle_order_engine: 乱序随机数引擎适配器
independent_bits_engine: 独立位随机数引擎适配器
discard_block_engine: 丢弃块随机数引擎适配器
default_random_engine: 默认的随机数引擎(最常用)
2.相关操作:
①C++中生成随机数
default_random_engine e;
e.seed((size_t)chrono::high_resolution_clock::now().time_since_epoch().count());
//等效这个:e.seed((size_t)time(NULL)); ->c语言风格->显然更好用、简洁
for (int i = 0; i < 3; i++)
{
//仿函数的方式生成随机数!!!
cout<<"随机数:" << e()%10 << endl; //通过取余固定范围
}
cout <<"max:"<< e.max() << endl; //生成随机数的上界
cout << "min:" << e.min() << endl; //生成随机数的下界
输出:
随机数:8
随机数:5
随机数:5
max:4294967295
min:0
②分布方式和引擎的方式
分布方式实际上也是一个需要实例化的仿函数,传入参数即默认引擎e,使得能够产生初始化区间内的随机数!!!
default_random_engine e;
uniform_int_distribution<int> duration(1, 6);
cout <<"uniform:"<< duration(e) << endl;
auto randDom = bind(duration, e);
cout << "sum:" << (randDom() + randDom() + randDom()) << endl;
输出:
uniform:5
sum:8
注:本处采用bind函数,将仿函数duration的唯一一个参数绑定为e
③了解部分 (适配器的实例化->产生随机数 等效于 直接用内置引擎)
注:引擎就是适配器的实例化 使用时直接用,不需要进行传参
(适配器的实例化有时会传入很多参数)(此部分直接查文档)
->直接用引擎的别名->但实际上用的最多的还是直接用default_random_engine
//3.1 线性同余 //x=(x*a+c)%m;
//适配器实例化 产生随机数
linear_congruential_engine<unsigned int, 1, 2, 8> ee;
e.seed((size_t)time(nullptr));//采用c语言风格的种子,一样可以
cout <<"线性同余:"<< ee() << endl;
mersenne_twister_engine<unsigned int, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1> em;
mt19937_64 eeee;//直接使用引擎,一般不采用上述的做法
cout << "梅森旋转:" << eeee() << endl;
输出:
线性同余:3
梅森旋转:14514284786278117030