在 C/C++ 中从双精度到int64_t的隐式转换是什么

What does implicit conversion from double to int64_t in C/C++

本文关键字:是什么 转换 int64 C++ 双精度      更新时间:2023-10-16

有人可以阐明此代码的行为方式:

double x = 9223371036854;
int64_t y1 = /* trunc */ (x * 1000000);
int64_t y2 = round(x * 1000000);
cout << y1 << " <= " << y2 << endl;
assert( y1 <= y2 ); // fail

此代码失败y1因为实际上等于9223371036854000000y2 9223371036853999616
取消注释后trunc一切正常(断言已验证)。

由 gcc-4.6.3-1ubuntu5 编译,g++ --std=c++0x x.cpp .

为什么int64_t(round(x * 1000000))小于int64_t(x * 1000000) x double

为什么int64_t(trunc(x * 1000000))的结果与int64_t(x * 1000000)不同?

我想我找到了为什么它像这样工作(y1 == 92233710368540000000和断言失败)。

GCC优化了y1的运行时计算,而不会损失精度,这显然发生在y2。更有趣的是,文字的表达没有这样的属性。

double x = 9223371036854;
int64_t y1 = /* trunc */ (x * 1000000);
int64_t y2 = round(x * 1000000);
cout << y1 << " <= " << y2 << endl;
assert( int64_t(9223371036854.0 * 1000000) <= int64_t(round(9223371036854e6)) ); // ok
assert( int64_t(x * 1000000) <= int64_t(round(x * 1000000)) ); // fails
assert( y1 <= y2 ); // fails

如果我1e6表达式之外移出,一切按预期工作:

double x = 9223371036854.0 * 1000000;
int64_t y1 = /* trunc */ (x);
int64_t y2 = round(x);
cout << y1 << " <= " << y2 << endl;
assert( int64_t(x) <= int64_t(round(x)) ); // ok
assert( y1 <= y2 ); // ok

但可能我对优化的假设是不正确的。