在C / C ++中从double到int64_t的隐式转换是什么?

时间:2013-09-12 08:43:56

标签: c++ c implicit-conversion

有人可以了解这段代码的行为方式:

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

我想我发现它为什么会这样(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

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