在 c++ 中 std::chrono::seconds 和 std::chrono::nanoseconds 之间的转换不会丢失信息

问题描述 投票:0回答:1

按照这个线程纳秒运行进入溢出,我的目的是自由地从纳秒和秒转换,但不会丢失任何信息(鉴于根据

std::chrono::nanoseconds
,纳秒是64位)。基本上,下面的代码会丢失很多信息:

std::chrono::nanoseconds t1(1705218518267805576);
std::chrono::seconds t2(std::chrono::duration_cast<std::chrono::seconds>(t1));
std::chrono::nanoseconds t3(std::chrono::duration_cast<std::chrono::nanoseconds>(t2));
EXPECT_EQ(t1,t3);

最后一行将返回 false。因此,我考虑添加诸如

long_data_seconds
之类的类型,它可以保存丢失的信息,但我不知道到底丢失了多少信息以及如何存储它以供将来转换使用。我很想听听想法。

非常感谢。

c++ integer-overflow c++-chrono
1个回答
0
投票

您面临的问题并不是(真的)由于

std::chrono::seconds
类型不够宽(即没有足够的位)来保存
nanoseconds
1的完整数据;相反,这是因为
seconds
类型是 integer。因此,当您将纳秒转换为秒时,由于截断,该值的小数部分(即小于 109的数据)的所有信息都会丢失。

在您的情况下,您需要为中间“秒”数据定义一个“浮点”持续时间类型。对于您给出的示例(1,705,218,518,267,805,576 ns),IEEE-754 double 类型不够精确,因此您需要一个支持

扩展精度
long double 类型的平台,并使用它。
这是一个简短的示例代码:

#include <iostream> #include <chrono> int main() { using ld_seconds = std::chrono::duration<long double, std::ratio<1>>; constexpr std::chrono::nanoseconds t1(1705218518267805576); constexpr ld_seconds t2(std::chrono::duration_cast<ld_seconds>(t1)); constexpr std::chrono::nanoseconds t3(std::chrono::duration_cast<std::chrono::nanoseconds>(t2)); static_assert(t1 == t3, "Not equal!"); return 0; }

这是关于 
Compiler Explorer

的演示。 如果您的平台上

long double

相当于

double
(例如 MSVC/Windows),那么您将需要使用第三方扩展精度库。


1

事实上,标准规定 std::chrono::seconds

至少
35 位 - 并且许多(大多数)当前平台没有大于 34 位但小于 64 位的内置整数类型,因此在这些系统上它可能是 int64_t
    

© www.soinside.com 2019 - 2024. All rights reserved.