c++ - 在两个分母的 LCM 都很大的 chrono::duration 类型之间转换

标签 c++ c++-chrono

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

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

当我使用::boost::chrono::duration_cast<>(或 std::chrono::duration_cast<>,就此而言),从 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 以获得一些值高位。 auto highbits = duration_cast<duration<CommonDuration::rep, ratio<CommonDuration::num>>>(tm);
  3. 将原始值tm减去highbits,得到lowbits值。 auto lowbits = tm - highbits;
  4. 将 duration_cast(lowbits) 的结果添加到 highbits。这是结果。 auto result = highbits + duration_cast<OtherType_T>(lowbits);

最佳答案

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

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,您仍然会溢出。

关于c++ - 在两个分母的 LCM 都很大的 chrono::duration 类型之间转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34600497/

相关文章:

c++ - std::string 到 std::chrono time_point

c++ - Java 到 C++ UTC 时间 - 以秒为单位查找 Utc 时区时间偏移

c++ - D3D11 - 将混合权重和索引传递给顶点着色器

android - 无法使用 jni 在 android Lollipop 中从 C++ 调用 JNI 到 java

c++ - 使用 MinGW windows 7 将静态库 .lib 转换为动态库 .dll

c++ - 如何修复 C++11 中 std::chrono 比较的编译错误?

c++ - 与 boost::date_time::not_a_date_time 等效的 C++11 是什么?

c++ - C++ : "error: int aaa::bbb is protected within this context" 上的错误

C++ Linux 中断 nanosleep