首页 > 解决方案 > 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] 有一些限制:

使用 double 显然满足了 of 的要求,rep而 theperiod显然是一个比率。剩下的是:是period时钟的滴答周期吗?

我不清楚这到底意味着什么。滴答周期是否代表时钟可能使用的最高精度?例如,time_since_epoch() 的余数,在不损失精度的情况下转换为秒,然后除以周期必须为零。当是整数类型时,这当然必须为真rep,但对于浮点类型,它可能不成立。这种解释似乎不允许上述时钟。

或者这是否意味着时钟应该以 为步长增加period,但有可能将滴答时间报告为子周期精度?这在精确时间戳中很常见。GPS 计时模块通常提供每秒脉冲 (PPS) 输出。这个脉冲不能在一个无限精确的瞬间产生,并且可能被限制在大约 10 ns 的步长内。但是,可以计算生成 PPS 的 10 ns 步长和它应该出现的更精确时刻之间的误差,并由硬件报告为校正值。因此,一个时钟每秒滴答一次,但每个滴答都以非零皮秒级的精度报告。

还是period唯一的意思是允许将持续时间从秒转换time_since_epoch()为秒?时钟的精度和滴答之间的预期时间都不需要与它有任何关系。

标签: c++chrono

解决方案


std::chrono-supplied 时钟的唯一要求rep是:

并且由于Cpp17TrivalClock要求

浮点类型满足所有这些要求。

在实践中,所有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_clocksystem_clock将度量转换为基于双精度的秒数。 my_clock是计时基础设施中的一等公民。例如你可以std::this_thread_sleep_until(my_clock::now() + 1s)

也就是说,您可以将durations 添加到您的 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 durationon和a based on和一个double-based 。doublesecondstime_pointsystem_clockseconds

这只是为我输出:

1631145273.043276

简而言之,的,基于浮点的时钟可以按其声明的几分之一进行计时period


推荐阅读