[英]strange double to int conversion behavior in c++
以下程序显示了我在c ++中看到的奇怪的double to int转换行为:
#include <stdlib.h>
#include <stdio.h>
int main() {
double d = 33222.221;
printf("d = %9.9g\n",d);
d *= 1000;
int i = (int)d;
printf("d = %9.9g | i = %d\n",d,i);
return 0;
}
当我编译并运行程序时,我看到:
g++ test.cpp
./a.out
d = 33222.221
d = 33222221 | i = 33222220
为什么我不等于33222221? 编译器版本是GCC 4.3.0
浮点表示几乎从不精确(仅在特殊情况下)。 每个程序员都应该读到: 每个计算机科学家应该知道的关于浮点运算的内容
简而言之 - 您的号码可能是33222220.9999999999999999999999999999999999999999999999999999999999999999998(或类似的东西),截断后变为33222220。
当你附加一个调试器,检查值,你会看到的价值d
实际上是33222220.999999996
,当转换为整数,这是正确截断为33222220。
可以存储在双变量中的数量有限,而33222221不是其中之一。
由于浮点近似,33222.221实际上可能是33222.220999999999999。 乘以1000得出33222220.999999999999。 强制转换为整数会忽略所有小数(向下舍入),最终结果为33222220。
如果将printf()
调用中的“9.9g”更改为17.17以使用64位IEEE 754 FP编号恢复所有可能的精度数字,则获得双精度值33222220.999999996。 然后int转换是有道理的。
我不想重复其他评论的解释。
所以,这里只是一个建议,以避免像所描述的问题:
尽可能避免浮点算法(特别是涉及计算时)。
如果确实需要浮点算术,那么一定不能通过operator ==比较数字! 使用你自己的比较函数(或使用一些库提供的函数),使用某种epsilon比较(绝对或相对于数字的magniture)做类似“几乎相等”的比较。
例如,参见优秀的文章
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
由布鲁斯道森代替!
斯特凡
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.