C++17中如何将纳秒级Unix时间戳转换为秒且不丢失精度
纳秒级Unix时间转秒丢失精度问题
我需要将纳秒级Unix时间转换为秒用于计算,但不想丢失精度。尝试将整数变量转为double类型,预期128除以10得到12.8,但实际转换后丢失了精度,仅得到整数部分。测试代码如下:
#include <iostream> #include <chrono> using namespace std; int main() { int64_t a = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); double b = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() / (1000 * 1000 * 1000); cout<<(a) << " ns \n"; cout.precision(9); cout << fixed << b << " s" << endl; return 0; }
输出结果:
1668199112421581468 ns 1668199112.000000000 s Wanted: 1668199112.421581468 s
问题出在整数除法上:
std::chrono::nanoseconds::count()返回的是int64_t类型整数,1000 * 1000 * 1000也是整数(值为1e9,属于int范围)。- C++中整数间的除法会直接舍弃小数部分,只保留整数结果,之后再转成
double自然丢失了小数位精度。
解决方法
把除数改成浮点数,让除法变成浮点数除法,三种方式任选其一:
- 直接使用浮点数常量
1e9:
double b = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() / 1e9;
- 把整数除数强制转为
double:
double b = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() / static_cast<double>(1000 * 1000 * 1000);
- 先把
count()结果转成double再做除法:
double b = static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) / (1000 * 1000 * 1000);
更简洁的方式
直接用std::chrono::duration<double>转换,无需手动计算除数:
double b = std::chrono::duration<double>(std::chrono::system_clock::now().time_since_epoch()).count();
注意:double的精度是53位二进制,对应约15-17位十进制数字。当前纳秒时间戳是19位左右,转成double后最后几位小数可能有微小精度损失,但多数场景下足够使用。若要完全无精度损失,建议使用高精度整数类型存储后再做运算。
内容的提问来源于stack exchange,提问作者gear
相关产品推荐
相关产品推荐

