在 C/C++ 中从双精度到int64_t的隐式转换是什么
What does implicit conversion from double to int64_t in C/C++
有人可以阐明此代码的行为方式:
double x = 9223371036854;
int64_t y1 = /* trunc */ (x * 1000000);
int64_t y2 = round(x * 1000000);
cout << y1 << " <= " << y2 << endl;
assert( y1 <= y2 ); // fail
此代码失败y1
因为实际上等于9223371036854000000
而y2
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
但可能我对优化的假设是不正确的。
相关文章:
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 从长整整转换为uint64_t的推荐方法是什么?
- C++:Lambda 函数指针转换的用例是什么?
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 为什么此指针值不能转换为整数的规则是什么?
- 指针类型类成员的动态强制转换的恒定性是什么?
- 将QGyroscopeReading转换为QVector3D的正确方法是什么?
- 在C++中将uint64_t转换为void类型的目的是什么
- 在C++中,将无符号整数转换为八进制表示,反之亦然的最佳方法是什么
- 这个typedef和转换运算符语法是什么意思
- 是什么将程序集转换为实际可执行的材料
- 转换为非标量误差是什么意思?我该如何解决?
- 在 OpenGL 中计算矩阵时,转换的正确顺序是什么?
- 统一初始化是隐式发生的,即使 int 强制转换运算符是使用 explicit 关键字声明的.原因是什么?
- C++ 将字符串数据包转换为 iphdr语言 - 字符串数据包的格式应该是什么?
- 将 24 位".bmp"图像转换为黑白/单色图像的可能算法是什么?
- 将强制转换运算符重载到 std::map 的正确语法是什么
- 初始化中的模板转换运算符类型推导规则是什么?
- 此错误的含义是什么:从 'char* [40] 转换为非标量类型 'std::string
- 转换逻辑目标是什么类型