std的时间函数——chrono

news2024/9/22 14:24:20

参考:

C++ 标准库 分数运算(ratio库)

再也不被时间束缚:C++ stdchrono时间库全面解析

C++11时间类

c++11 chrono全面解析(最高可达纳秒级别的精度)

C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)

一、std的分数ratio

    在进行时间库之前,先看看std定义的分数,顺便,看看英文.....

template<intmax_t _Num, intmax_t _Den = 1>
struct ratio
{
    static_assert(_Den != 0, "denominator cannot be zero");
    static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__,
		  "out of range");

    // Note: sign(N) * abs(N) == N
    static constexpr intmax_t num =
      _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value;

    static constexpr intmax_t den =
      __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value;

    typedef ratio<num, den> type;
};

函数原型还是很朴实的,很容易理解,也就是说ratio包括3个成员,num、den和type,num表示分子,den表示分母,type是类型,而且是最简约分形式(说到这,想起一到leetcode题,大概意思就是,给两个数,以字符串输出相除的结果,如果是无限循环小数,比如1/3,就输出0.(3) 这种形式)。

1.1 ratio的函数

例如

type返回的一个是ratio<>,2/7+2/6=13/21
typedef std::ratio_add<std::ratio<2, 7>, std::ratio<2, 6>>::type test;
 
std::cout << test::num << "/" << test::den << std::endl;
std::cout << std::ratio_equal<std::ratio<1, 3>, std::ratio<1, 3>>::value << std::endl;    // true
std::cout << std::ratio_equal<std::ratio<2, 3>, std::ratio<1, 3>>::value << std::endl;    // false
std::cout << std::ratio_greater<std::ratio<2, 3>, std::ratio<1, 3>>::value << std::endl;    // true

1.2 使用注意

  • ratio定义时,其分母不能定义为0,否则编译不通过
  • ratio定义时,如果不填分母,默认为1
  • 如果分子无-号,分母有-号,分母的-号会被移动到分子身上
  • 如果分子有-号,分母无-号,则分子的-号保持不动
  • 如果分子分母都有-号,则-号都被消除
  • 分子可以为0
  • ratio会自动对分子和分母进行约分

例如

//无法编译通过,因为1/max乘以1/2会导致溢出,分母超过了其类型所能涵盖的极限
std::ratio_multiply<std::ratio<1, std::numeric_limits<long long>::max()>, std::ratio<1, 2>>::type;



// 表达式也无法通过编译,因为其除以了0:
typedef ratio<5, 3> FiveThirds;
typedef ratio<0> zero;          //分子为0,分母默认为1
std::ratio_divide<FiveThirds, zero>::type;



// 但是下面的可以编译通过,因为下面只使用了ratio_divide<>,却没有实例化一个ratio<>对象,因此编译器检测不出来
typedef ratio<5, 3> FiveThirds;
typedef ratio<0> zero;
std::ratio_divide<FiveThirds, zero>; //只调用了ratio_divide,却没有实例化出任何ratio对象

1.3 stl的自定义类型

typedef ratio<1, 1000000000000000000LL>  atto;  // 微微微
typedef ratio<1, 1000000000000000LL>     femto; // 飞秒
typedef ratio<1, 1000000000000LL>        pico;  // 皮秒
 
typedef ratio<1, 1000000000>             nano;  // 纳秒
typedef ratio<1, 1000000>                micro; // 微秒
typedef ratio<1, 1000>                   milli; // 毫秒
typedef ratio<1, 100>                    centi; // centi:百分之一
typedef ratio<1, 10>                     deci;  // deci:十分之一
typedef ratio<10, 1>                     deca;  // deci:十倍
typedef ratio<100, 1>                    hecto; // hecto:百倍
typedef ratio<1000, 1>                   kilo;  // 千
typedef ratio<1000000, 1>                mega;  // 兆
typedef ratio<1000000000, 1>             giga;  // 吉
 
typedef ratio<1000000000000LL, 1>        tera;  // 太
typedef ratio<1000000000000000LL, 1>     peta;  // 拍
typedef ratio<1000000000000000000LL, 1>  exa;   // 百亿亿

二、chrono库

    chrono库三大组件:时间段(duration)、时间点(time_point)和时钟(clock)。

2.1 duration

    类模板原型是

template<class _Rep,class _Period>
class duration

其中,_Rep可以理解为数值,Period可以理解为数值单位。例如

std::chrono::duration<int, std::ratio<1, 1>> ts(2)

表示数值是整形,单位是s,也就是表示2s,再例如

std::chrono::duration<float, std::ratio<1, 1>> ts(2.2)

表示数值是float,单位是秒,也就是2.2s

如果想调整数值,可以使用int,float,double。如果想改变单位,就是一切以std::ratio<1, 1>(也就是std::ratio<1>)为基准,比如

std::chrono::duration<float, std::ratio<10, 1>> ts(2.2)
// 等价std::chrono::duration<float, std::deca> ts(2.2)

表示2.2个10s,就是22秒,前面标准库定义了许多比率,可以直接拿来使用。再例如

std::chrono::duration<float, std::ratio<1, 10>> ts(2.2)
// 等价std::chrono::duration<float, std::deci> ts(2.2)

表示2.2个0.1s,也就是0.22s。自然,时间表述有时、分、秒、毫秒、微妙等等,时间chrono定义了这些概念

typedef duration<long long, nano> nanoseconds;
typedef duration<long long, micro> microseconds;
typedef duration<long long, milli> milliseconds;
typedef duration<long long> seconds;
typedef duration<long long, ratio<60>> minutes;
typedef duration<long long, ratio<3600>> hours;

因此上面的0.22s可以表示为

std::chrono::seconds ts(0.22);
// 或者std::chrono::milliseconds ts(220);

2.1.1 操作方法

duration构造的方法包括默认构造,拷贝构造和传递数值构造,例如

std::chrono::duration<int, std::milli> duration0;  // 默认构造
std::chrono::duration<int, std::milli> duration1(500); // 传递数值
std::chrono::duration<double, std::ratio<1, 100>> duration2 = duration1; // 传递duration对象(即使单位不同也性)
// duration0:0  duration1:500  duration2:50

    chrono提供了对duration加减乘除以及比较的方法,例如

std::chrono::duration<int, std::milli> duration1(500);
std::chrono::duration<double, std::nano> duration2(1.5);
std::chrono::duration<float, std::micro> duration3 = duration1 + duration2; // 表示501.5微秒
// std::chrono::duration<int, std::micro> duration3 = duration1 + duration2; // 错误

数值类型int可以转换成double或float,但是double和float不能转换成int,但是double和float两者可以互相转换。

    再例如乘除:

std::chrono::duration<int, std::milli> duration4 = duration1 * 2; // 表示1000毫秒
std::chrono::duration<double, std::milli> duration5 = duration2 / 2; // 表示0.75毫秒

    duration还可以做逻辑比较(<、<=、>、>=、==、!=)例如

std::chrono::duration<int, std::milli> duration1(500);
std::chrono::duration<double, std::nano> duration2(1.5);
bool result = duration1 > duration2; // 返回true,因为500毫秒大于1.5纳秒

     duration还提供了单位转换函数duration_cast,例如

std::chrono::hours hour_time = std::chrono::hours(1);

std::chrono::minutes minutes_time = std::chrono::duration_cast<std::chrono::minutes>(hour_time);

std::chrono::seconds seconds_time = std::chrono::duration_cast<std::chrono::seconds>(hour_time);

std::chrono::milliseconds milliseconds_time = std::chrono::duration_cast<std::chrono::milliseconds>(hour_time);

std::chrono::microseconds microseconds_time = std::chrono::duration_cast<std::chrono::microseconds>(hour_time);

 也就是类型转换函数。

2.2 clock

    时间点就是某时刻的时间点,而想要获得时间点,肯定需要时钟,而chrono提供了3个时钟:system_clock、steady_clock和high_resolution_clock

2.2.1 system_clock

函数原型如下:

struct system_clock{
    typedef chrono::nanoseconds     			duration;
    typedef duration::rep    					rep;
    typedef duration::period 					period;
    typedef chrono::time_point<system_clock, duration> 	time_point;

    static_assert(system_clock::duration::min()
		    < system_clock::duration::zero(),
		    "a clock's minimum duration cannot be less than its epoch");

    static constexpr bool is_steady = false;

    static time_point now() noexcept;

      // Map to C API
    static std::time_t to_time_t(const time_point& __t) noexcept{
	    return std::time_t(duration_cast<chrono::seconds>
			   (__t.time_since_epoch()).count());
    }

    static time_point from_time_t(std::time_t __t) noexcept
    {
	    typedef chrono::time_point<system_clock, seconds>	__from;
	    return time_point_cast<system_clock::duration>(__from(chrono::seconds(__t)));
    }
};

可见system_clock的精度是纳秒,提供了now函数、to_time_t和from_time_t函数接口。

2.2.2 steady_clock

struct steady_clock{
    typedef chrono::nanoseconds 				duration;
    typedef duration::rep	  				    rep;
    typedef duration::period	  				period;
    typedef chrono::time_point<steady_clock, duration> 	time_point;

    static constexpr bool is_steady = true;

    static time_point now() noexcept;
};

 steady_clock的精度是纳秒,只提供了now接口。

2.2.3 high_resolution_clock

using high_resolution_clock = system_clock;

high_resolution_clock就是system_clock。

2.2.4 总结

auto tp0 = std::chrono::system_clock::now();
auto tp1 = std::chrono::steady_clock::now();
auto tp2 = std::chrono::high_resolution_clock::now();

std::cout << tp0.time_since_epoch().count() << std::endl;
std::cout << tp1.time_since_epoch().count() << std::endl;
std::cout << tp2.time_since_epoch().count() << std::endl;

上述输出结果,在我的电脑上 system_clock和high_resolution_clock是相同的,都是从1970年1月1日0时0分0秒开始的,以纳秒为单位的结果。而steady_clock则是从上次开机到现在递增增加的时间结果(这里我的电脑是这样的,ubuntu系统可以通过last reboot或uptime指令查看上次开机时间但是这两个数值可能不一样,只有一个是准确的),单位时纳秒。

  1. system_clock:(1)系统级别的时钟,它表示实时时钟,也就是指示当前时间的时钟。它的时间点是与系统的时钟相关联的,可能受到时钟调整和时区的影响,或者网络自动调整时间。(2)获取当前的系统时间,可以用来进行日常时间计算和显示。它通常被用作默认的时钟类型。
  2. steady_clock:是一个单调递增的时钟,不受任何时钟调整或时区的影响。它提供了一个稳定、可靠的时间基准,适合用于测量时间间隔和计算算法的执行时间。
  3. high_resolution_clock:是一个可用于测量小时间间隔的时钟。它通常使用最高分辨率的时钟源来提供更高的时间精度。在大部分平台上,high_resolution_clock是steady_clock的别名,因此也是一个单调递增的时钟。

2.3 time_point

    结构体原型:

template<typename _Clock, typename _Dur>
struct time_point
{
	typedef _Clock			  			clock;
	typedef _Dur		  				duration;
	typedef typename duration::rep	  	rep;
	typedef typename duration::period	period;

	constexpr time_point() : __d(duration::zero())
	{ }

	constexpr explicit time_point(const duration& __dur)
	    : __d(__dur)
	{ }

	// conversions
	template<typename _Dur2, typename = _Require<is_convertible<_Dur2, _Dur>>>
	constexpr time_point(const time_point<clock, _Dur2>& __t)
	    : __d(__t.time_since_epoch())
	{ }

	// observer
	constexpr duration time_since_epoch() const
	{ return __d; }

	// arithmetic
	_GLIBCXX17_CONSTEXPR time_point& operator+=(const duration& __dur)
	{
	  __d += __dur;
	  return *this;
	}

	_GLIBCXX17_CONSTEXPR time_point& operator-=(const duration& __dur)
	{
	  __d -= __dur;
	  return *this;
	}

	// special values
	static constexpr time_point	min() noexcept
	{ return time_point(duration::min()); }

	static constexpr time_point	max() noexcept
	{ return time_point(duration::max()); }

private:
	duration __d;
};

    time_point则是根据不同的时钟获取时钟的时间点。例如

system_clock::time_point now = system_clock::now();
system_clock::time_point specific_time = system_clock::time_point(seconds(100000));
system_clock::time_point specific_time(seconds(100000));

std::cout << now_sys.time_since_epoch().count() << std::endl;
std::cout << specific_time0.time_since_epoch().count() << std::endl;
std::cout << specific_time1.time_since_epoch().count() << std::endl;

输出

1721640151178784335
100000000000000
100000000000000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1943281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 防止重复点击

1.第一种方式&#xff1a; private static final int MIN_DELAY_TIME 2000; // 两次点击间隔不能少于2000ms private static long lastClickTime System.currentTimeMillis(); public static boolean isFastClick() { boolean flag true; long currentClickTime …

JMeter接口测试-3.断言及参数化测试

1. 断言 JMeter官方断言&#xff08;Assertion&#xff09;的定义 用于检查测试中得到的响应数据是否符合预期&#xff0c;用于保证测试过程中的数据交互与预期一致 断言的目的&#xff1a; 一个取样器可以添加多个不同形式的断言&#xff0c;根据你的检查需求来添加相应的…

dou dian滑块captchaBody

声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 前言(lianxi a…

基于生物地理算法的MLP多层感知机优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 生物地理算法&#xff08;BBO&#xff09;原理 4.2 多层感知机&#xff08;MLP&#xff09; 4.3 BBO优化MLP参数 5.完整程序 1.程序功能描述 基于生物地理算法的MLP多层感知机优化mat…

Git之repo sync -l与repo forall -c git checkout用法区别(四十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Java 集合框架:TreeMap 的介绍、使用、原理与源码解析

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 021 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口

SpringBoot原理解析&#xff08;二&#xff09;- Spring Bean的生命周期以及后处理器和回调接口 文章目录 SpringBoot原理解析&#xff08;二&#xff09;- Spring Bean的生命周期以及后处理器和回调接口1.Bean的实例化阶段1.1.Bean 实例化的基本流程1.2.Bean 实例化图例1.3.实…

leetcode算法题之接雨水

这是一道很经典的题目&#xff0c;问题如下&#xff1a; 题目地址 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 解法1&#xff1a;动态规划 动态规划的核心就是将问题拆分成若干个子问题求解&#…

相信开源的力量,MoonBit 构建系统正式开源

MoonBit 构建系统正式开源 作为由 AI 驱动的云服务和边缘计算开发者平台&#xff0c;MoonBit 自设计之初便注重工具链与语言的协同效果。MoonBit 为开发者提供了一套开箱即用的工具链&#xff0c;包括集成开发环境&#xff08;IDE&#xff09;、编译器、构建系统和包管理器&…

内网隧道——HTTP隧道

文章目录 一、ReGeorg二、Neo-reGeorg三、Pivotnacci 实验网络拓扑如下&#xff1a; 攻击机kali IP&#xff1a;192.168.111.0 跳板机win7 IP&#xff1a;192.168.111.128&#xff0c;192.168.52.143 靶机win server 2008 IP&#xff1a;192.168.52.138 攻击机与Web服务器彼此之…

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 目录 Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 一、简单介绍 二、共享纹理 1、共享纹理的原理 2、共享纹理涉及到的关键知识点 3、什么可以实现共享 不能实现共享…

越权与逻辑漏洞

目录 越权漏洞 1、越权原理概述 2、越权分类 2.1、平行越权 2.2、垂直越权 3、越权防范&#xff1a; 逻辑漏洞 1、常见的逻辑漏洞 2、逻辑漏洞概述 3、逻辑漏洞防范&#xff1a; 越权漏洞 1、越权原理概述 如果使用A用户的权限去操作B用户的数据&#xff0c;A的权限…

静态路由技术

一、路由的概念 路由是指指导IP报文发送的路径信息。 二、路由表的结构 1、Destination/Mask:IP报文的接收方的IP地址及其子网掩码; 2、proto:协议(Static:静态路由协议,Direct:表示直连路由) 3、pref:优先级(数值和优先级成反比) 4、cost:路由开销(从源到目的…

jQuery下落撞击散乱动画

jQuery下落撞击散乱动画https://www.bootstrapmb.com/item/14767 在jQuery中实现一个下落撞击后散乱的动画效果&#xff0c;你可以结合CSS动画和jQuery的动画函数来完成。不过&#xff0c;由于jQuery本身并不直接支持复杂的物理效果&#xff08;如撞击后的散乱&#xff09;&a…

Nessus-M 暴力破解Nessus漏扫后台登录工具

项目地址:https://github.com/MartinxMax/Nessus-M Nessus-M Nessus漏洞扫描程序登录界面的暴力破解工具 帮助信息 $ python3 nessus-m.py -h 暴力破解 $ python3 nessus-m.py 192.168.101.156 8834 username.txt /usr/share/wordlists/rockyou.txt --protocol https

贪心系列专题篇二

增减字符串匹配 题目 思路 贪心策略&#xff1a;对于[0,n]&#xff0c;当遇到“I”时&#xff0c;把所剩的数中最小的拿来使用&#xff1b; 当遇到“D”时&#xff0c;把所剩的数中最大的拿来使用&#xff0c;最后还剩一个数&#xff0c;放末尾。 代码 class Solution { pu…

sbti科学碳目标倡议是什么

在科学界、工业界以及全球政策制定者的共同努力下&#xff0c;一个名为“科学碳目标倡议”&#xff08;Science Based Targets initiative&#xff0c;简称SBTi&#xff09;的全球性合作平台应运而生。这一倡议旨在推动企业和组织设定符合气候科学要求的减排目标&#xff0c;以…

Nginx 如何处理请求的限速?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; 文章目录 Nginx 如何处理请求的限速一、为什么需要对请求进行限速&#xff08;一&#xff09;服务器过载&#xff08;二&#xff09;资源竞争&#xff08;三&#xff09;服…

数据接入开放协议-GRPC接入

协议定义 一、接入认证 message VerifyRequest { string authToken 1; // 接入管理分配的UUID string endpointName 2; // 定义的接入设备名 string endpointIdentify 3; // 接入设备的ID int64 leaseValue 4; // 租约时间,接入侧申明数据上送间隔最大时间&…

JWT令牌在项目中的实战操作

一.什么是JWT令牌&#xff1f; JWT&#xff0c;全称JSON Web Token&#xff0c;官网&#xff08;https://jwt.io/&#xff09;&#xff0c;定义了一种间接的&#xff0c;自包含的格式&#xff0c;用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在&#xff0c;…