请考虑以下代码段:
float f = 0.01 ;
printf("%f\n",f - 0.01);
if (f - 0.01 == 0)
{
printf("%f\n",f - 0.01);
}
当我运行此代码时,对于第二行,我得到输出-0.000000
,并且if条件不会执行。
-0.000000
我记得在大学录取的数字逻辑课程中,这是由于使用一个补码的内部表示而产生的。如果我错了请纠正我,请建议修复以及将来如何避免这种情况。
如果重要的话,我正在使用clang来编译我的代码。
答案 0 :(得分:4)
你遇到两个问题:
0.01
无法完全表示为二进制浮点值f
的类型为float
,而0.01
的类型为double
您的计算需要从double
转换为float
,然后返回(显然)不会提供与其开头时完全相同的值。
您可以通过坚持所有值的单一类型(float
或double
)来修复此特定示例;但如果你想比较更复杂计算的结果以确保完全相等,你仍会遇到问题。
答案 1 :(得分:1)
0.01
是double
而不是float
(编译代码时可能会收到警告。)
所以,你基本上是在浮动和双打之间向前和向后转换你的“0.01”,这就是导致你出现差异的原因。
因此,决定是否要使用浮点数(例如0.01f
)或双打,并坚持使用一个版本。
然而,正如其他答案所指出的那样,在进行浮点运算时,你永远不会得到“精确”值 - 它只是不起作用。
作为参考,这两个版本都会给出你期待的答案
float f = 0.01f ;
printf("%f\n",f - 0.01f);
if (f - 0.01f == 0)
{
printf("%f\n",f - 0.01f);
}
或
double f = 0.01 ;
printf("%f\n",f - 0.01);
if (f - 0.01 == 0)
{
printf("%f\n",f - 0.01);
}
都打印
0.000000
0.000000
答案 2 :(得分:0)
原因是,0.01
无法在二进制浮点数中正确表示。这可以通过一个例子来理解:10/3
给出结果3.333333333333333.....
。,即它不能以十进制正确表示。与0.01
类似的情况。每个浮点十进制数都无法在二进制浮点等效值中正确表示。
答案 3 :(得分:0)
你有两个双0.01 - 一个被转换成一个浮点数。由于精度损失双倍(浮点数(0.01))!=双倍(0.01)
即使没有明显的精度损失,您也可能只会使用double(s)而遇到麻烦。编译器可能会将一个作为扩展的double保留在寄存器中,并从内存中获取另一个(存储为double)