c++ - std::chrono 时钟允许使用带有小数部分的浮点表示
问题描述
是否允许实现提供使用浮点表示且周期大于时钟分辨率的时钟?
如果周期大于分辨率,则持续时间的浮点值可能有小数部分。或在代码中:
const auto t = std::chrono::high_resolution_clock::now();
modf(t.time_since_epoch().count(), &dummy) != 0;
如果时钟的下级表示是整数类型,那么显然上述比较肯定是错误的。使用浮点表示是可能的,但是标准允许吗?
例如std::chrono::high_resolution_clock
,分辨率为 1 微秒,定义为:
class high_resolution_clock {
public:
typedef double rep;
typedef ratio<1, 1> period; // Note, 1 sec period > 1 µs resolution
typedef chrono::duration<rep, period> duration;
这与 Pythontime.time()
返回系统时间的方式非常相似。
rep
并且period
在标准中未指定,但 N4860 §27.3 表 97 [time.clock.req] 有一些限制:
rep
必须是“[a]n 算术类型或模拟算术类型的类”period
必须是“比率的专业化”period
是“[t]时钟的滴答周期,以秒为单位”
使用 double 显然满足了 of 的要求,rep
而 theperiod
显然是一个比率。剩下的是:是period
时钟的滴答周期吗?
我不清楚这到底意味着什么。滴答周期是否代表时钟可能使用的最高精度?例如,time_since_epoch() 的余数,在不损失精度的情况下转换为秒,然后除以周期必须为零。当是整数类型时,这当然必须为真rep
,但对于浮点类型,它可能不成立。这种解释似乎不允许上述时钟。
或者这是否意味着时钟应该以 为步长增加period
,但有可能将滴答时间报告为子周期精度?这在精确时间戳中很常见。GPS 计时模块通常提供每秒脉冲 (PPS) 输出。这个脉冲不能在一个无限精确的瞬间产生,并且可能被限制在大约 10 ns 的步长内。但是,可以计算生成 PPS 的 10 ns 步长和它应该出现的更精确时刻之间的误差,并由硬件报告为校正值。因此,一个时钟每秒滴答一次,但每个滴答都以非零皮秒级的精度报告。
还是period
唯一的意思是允许将持续时间从秒转换time_since_epoch()
为秒?时钟的精度和滴答之间的预期时间都不需要与它有任何关系。
解决方案
对std::chrono
-supplied 时钟的唯一要求rep
是:
rep
必须是算术类型或模拟算术类型的类:https ://eel.is/c++draft/time.clock.req#tab:time.clock-row-2
并且由于Cpp17TrivalClock要求:
rep
符合数字类型要求:https ://eel.is/c++draft/time.clock.req#4.2对于
system_clock
,rep
必须签名: http ://eel.is/c++draft/time.clock#system.members-1
浮点类型满足所有这些要求。
在实践中,所有std::chrono
提供的时钟都使用有符号积分rep
。
但是请注意,提供自己的时钟几乎是微不足道的:
#include <chrono>
struct my_clock
{
using rep = double;
using period = std::ratio<1>;
using duration = std::chrono::duration<rep, period>;
using time_point = std::chrono::time_point<my_clock>;
static constexpr bool is_steady = false;
static time_point now() noexcept
{
return time_point{std::chrono::system_clock::now().time_since_epoch()};
}
};
在此示例中,我基于my_clock
但system_clock
将度量转换为基于双精度的秒数。 my_clock
是计时基础设施中的一等公民。例如你可以std::this_thread_sleep_until(my_clock::now() + 1s)
。
也就是说,您可以将duration
s 添加到您的 customtime_point
中,并在 std 提供的函数中使用它,该函数需要time_point
.
time_point
您还可以根据提供的std::chrono
时钟形成自己的浮点数。例如:
using dsec = std::chrono::duration<double>;
using dtp = std::chrono::time_point<std::chrono::system_clock, dsec>;
dtp tp = std::chrono::system_clock::now();
std::cout << std::fixed << tp.time_since_epoch().count() << '\n';
上面形成了一个带有句号的a based duration
on和a based on和一个double-based 。double
seconds
time_point
system_clock
seconds
这只是为我输出:
1631145273.043276
简而言之,是的,基于浮点的时钟可以按其声明的几分之一进行计时period
。
推荐阅读
- security - 你能利用 emscripten 编译的 Wasm 来运行任意 JavaScript 吗?
- ios - iOS - 在后台发现 BLE
- uwp - 在 Surface 平板电脑上安装的 UWP App 上打开应用程序时如何通过代码显示键盘?
- angular - Angular Tomcat 部署问题
- aem - 需要加载预先填充特定记录的 AEM 表单
- javascript - 在不调用函数的情况下切换 amchart 图形类型
- java - 为什么在 Java 中使用 Random 时会出错?
- sql - 将值与同一表中的其他行进行比较并返回聚合结果
- python - 实例变量不变
- reactjs - React-big-calendar,当视图更改为周、工作周、日时发出喙。如何解决?