目前我正在使用boost::rational<std::uint64>
跟踪我的应用程序。
基本上我有一个在很长一段时间内运行的时钟,并且会被不同时间分辨率的不同组件勾选,例如: 1 / 50s,1 / 30s,1001 / 30000s等...我想保持完美的精度,即没有浮点。 boost::rational
可以很好地实现此目的,但我认为使用std::chrono::duration
进行此设计会更好。
我的问题是,我如何在这里使用std::chrono::duration
?由于它使用编译时间段,我不太清楚如何在我需要保持精度的场景中使用它?
答案 0 :(得分:2)
如果我理解你的问题, if 你在编译时知道所有不同的时间分辨率,那么以下内容将按照您的意愿行事。您可以在所有不同的时间分辨率上使用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()));
}
};
这将在编译时计算最大的滴答周期,它将精确地代表您指定的每个分辨率。例如,使用此时钟可以准确表示:
下面的代码练习了这个clock
,并使用here描述的“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
含义:调用now()
之间有633个时钟滴答,每个滴答的单位是1/30000秒。如果您不想被“chrono_io”所感染,可以使用clock::period::num
和clock::period::den
来检查时钟单位。
如果您的不同时间分辨率不是编译时信息,则使用boost::rational
的当前解决方案可能是最佳解决方案。
答案 1 :(得分:1)
您可以将句点设置为1
并使用Rep
的浮点类型。
我怀疑您可以使用boost::rational
执行相同的操作,但是您必须仔细查看std::chrono
,我还没有这样做。查看treat_as_floating_point
和duration_values
。还要尝试通过“算术类型或模拟算术类型的类”来确定标准的含义。
有人可能会合理地争辩说,如果boost::rational
不能模拟算术类型,那么它就不会完成它的工作。但它并非必然遵循它真正做到std::chrono::duration
所期望的所有事情。