1

目前我boost::rational<std::uint64>用来跟踪我的应用程序。

基本上我有一个运行很长时间的时钟,并且会被不同时间分辨率的不同组件打勾,例如1/50s、1/30s、1001/30000s等......我想保持完美的精度,即没有浮点数。boost::rational为此目的效果很好,但是我认为为此使用它会更好std::chrono::duration

我的问题是,我怎么能std::chrono::duration在这里使用?由于它使用编译时间段,我不太明白如何在需要保持精度的场景中使用它?

4

2 回答 2

4

如果我理解您的问题,并且如果您在编译时知道所有不同的时间分辨率,那么以下内容将满足您的需求。您可以通过使用所有不同的时间分辨率来计算正确的刻度周期,common_type如下所示:

#include <cstdint>
#include <chrono>

struct clock
{
    typedef std::uint64_t                      rep;
    typedef std::common_type
    <
        std::chrono::duration<rep, std::ratio<1, 50>>,
        std::chrono::duration<rep, std::ratio<1, 30>>,
        std::chrono::duration<rep, std::ratio<1001, 30000>>
    >::type                                    duration;
    typedef duration::period                   period;
    typedef std::chrono::time_point<clock>     time_point;
    static const bool is_steady =              true;

    static time_point now()
    {
        // just as an example
        using namespace std::chrono;
        return time_point(duration_cast<duration>(steady_clock::now().time_since_epoch()));
    }
};

这将在编译时计算最大的刻度周期,它将准确地代表您指定的每个分辨率。例如,用这个时钟可以准确地表示:

  • 1/50 有 600 个刻度。
  • 1/30 有 1000 个刻度。
  • 1001/30000 有 1001 个刻度。

下面的代码对此进行了练习,并使用此处clock描述的“chrono_io”工具不仅打印出时钟滴答的运行时数量,还打印出时钟滴答的编译时间单位:

#include <iostream>
#include <thread>
#include "chrono_io"

int main()
{
    auto t0 = clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    auto t1 = clock::now();
    std::cout << (t1-t0) << '\n';
}

对我来说,这打印出来:

633 [1/30000]seconds

含义:调用之间有 633 个时钟滴答now(),每个滴答的单位是 1/30000 秒。如果您不想受制于“chrono_io”,您可以使用clock::period::num和检查时钟的单位clock::period::den

如果您的不同时间分辨率不是编译时信息,那么您当前的解决方案boost::rational可能是最好的。

于 2012-11-17T23:12:55.930 回答
1

您可以将周期设置为1并使用浮点类型Rep

怀疑你可以用 做同样的事情boost::rational,但你必须仔细观察std::chrono,我没有这样做。看treat_as_floating_pointduration_values。还要尝试通过“算术类型或模拟算术类型的类”来弄清楚标准的含义。

有人可能会合理地争辩说,如果boost::rational不模拟算术类型,那么它就没有做好它的工作。但这并不一定意味着它确实做到了std::chrono::duration预期的一切。

于 2012-10-08T18:52:31.953 回答