在chrono :: duration类型之间转换,其中两个分母的LCM都很大

时间:2016-01-04 21:49:03

标签: c++ chrono

我遇到了一个问题,我不得不在两种不同的持续时间类型之间进行转换,如下所示:

using MyType_T = duration<long long, ratio<1, 4294967296LL>>;
using OtherType_T = duration<long long, ratio<1, 10000000>>;

当我使用:: boost :: chrono :: duration_cast&lt;&gt; (或std :: chrono :: duration_cast&lt;&gt;,就此问题而言),从MyType_T转到OtherType_T,反之亦然,我发现当源值超过某个限制时,这些类型的转换会产生错误的结果。

仅调用duration_cast(tm)存在问题的原因是两个分母的LCM完全以56位表示。在这种情况下,通过将tm中的值除以分母的LCM,并将其作为公共因子类型传递到OtherType_T持续时间的构造中来完成转换。这将执行乘法以获得正确的值。

正如您所看到的,如果值足够大(在这种情况下为64或更大),这意味着除法可以将所有内容都移到零,并且您什么也得不到。

除了执行以下操作之外,有没有办法在不失去所有精度的情况下进行此转换?

  1. 创建一个新类型Interim_T,它只是两者的common_type,并删除了分母。 typedef typename common_type<MyType_T, OtherType_T>::type CommonDuration;
  2. 对“From”值tm执行duration_cast到新类型,以获得一些值highbits。 auto highbits = duration_cast<duration<CommonDuration::rep, ratio<CommonDuration::num>>>(tm);
  3. 从原始值tm中减去高位,以获得低位值。 auto lowbits = tm - highbits;
  4. 要高位,请添加duration_cast(lowbits)的结果。这是结果。 auto result = highbits + duration_cast<OtherType_T>(lowbits);

1 个答案:

答案 0 :(得分:1)

我会使用浮点类型作为临时类型:

using MyType_T = duration<long long, ratio<1, 4294967296LL>>;
using OtherType_T = duration<long long, ratio<1, 10000000>>;
using OtherType_F = duration<long double, OtherType_T::period>;

MyType_T x{0x7FFFFFFFFFFF};
auto y = duration_cast<OtherType_T>(OtherType_F{x});

语法更容易,逻辑也不那么复杂。请注意,如果结果不适合OtherType_T,您仍会溢出。