繁体   English   中英

在c ++中奇怪的双重转换行为

[英]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转换是有道理的。

我不想重复其他评论的解释。

所以,这里只是一个建议,以避免像所描述的问题:

  1. 尽可能避免浮点算法(特别是涉及计算时)。

  2. 如果确实需要浮点算术,那么一定不能通过operator ==比较数字! 使用你自己的比较函数(或使用一些库提供的函数),使用某种epsilon比较(绝对或相对于数字的magniture)做类似“几乎相等”的比较。

例如,参见优秀的文章

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

由布鲁斯道森代替!

斯特凡

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM