C++ c++;

C++ c++;,c++,type-conversion,C++,Type Conversion,下面的程序显示了我在c++中看到的奇怪的双精度到整数转换行为: #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; } 为什么我不等于332221?

下面的程序显示了我在c++中看到的奇怪的双精度到整数转换行为:

#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;
}
为什么我不等于332221?
编译器版本为GCC 4.3.0

浮点表示几乎从不精确(仅在特殊情况下)。每个程序员都应该阅读以下内容:


简而言之,您的数字可能是3322220.9999999999999999999999999999999999999999999999999999999999999999999998(或类似的数字),在截断后变为3322220。

由于浮点近似,33222.221实际上可能是33222.22099999999999。乘以1000得到332220.9999999。转换为整数将忽略最终结果332220的所有小数(向下舍入)。

当您附加调试器并检查值时,您将看到
d
的值实际上是
332220.9999999 6
,转换为整数时将正确截断为3322220


双变量中可以存储的数字数量有限,3322221不是其中之一。

如果将
printf()调用中的“9.9g”更改为17.17以恢复64位IEEE 754 FP数字的所有可能精度数字,则双变量值为3322220.999996。int转换是有意义的。

我不想重复其他注释的解释

因此,这里只是一个建议,以避免出现上述问题:

  • 在可能的情况下,首先避免使用浮点算术(尤其是在涉及计算时)

  • 若浮点算术确实是必要的,那个么千万不要通过运算符==来比较数字!使用您自己的比较函数(或者使用某个库提供的函数),它使用某种epsilon比较(绝对或相对于数字的magniture)进行类似“几乎相等”的比较

  • 例如,参见优秀文章

    http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
    
    由布鲁斯·道森代替


    Stefan

    好的,谢谢,这很有道理。那么,在不必担心这个问题的情况下,转换为int的首选方法是什么?圆函数?(但这仍然涉及到双->整数转换…)user924:inti=(int)(d>=0?d+0.5:d-0.5);解决您的问题添加0.5将以“四舍五入”结束。如果您想要“向下取整”,但是有一点空间来纠正这种不精确性,那么您可以添加一个较小的值。例如
    (d+0.001)
    ,或
    (d+d*DBL\u EPSILON)
    。如果您要将数字乘以1000,并且希望得到正确的结果,那么可以使用一个十进制算术库。或者只使用C99数学库中的
    i=(int)nearbyint(d)
    。当然,如果舍入模式与您想要舍入的方式匹配,那么可以使用。实际上,3322221就是其中之一。这里的问题是33222.221不是。
    http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm