C++ 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?
#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