关于c中浮点运算的异常,从自身中减去一个数

时间:2014-01-27 14:55:02

标签: c++ c floating-point

请考虑以下代码段:

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来编译我的代码。

4 个答案:

答案 0 :(得分:4)

你遇到两个问题:

  • 0.01无法完全表示为二进制浮点值
  • f的类型为float,而0.01的类型为double

您的计算需要从double转换为float,然后返回(显然)不会提供与其开头时完全相同的值。

您可以通过坚持所有值的单一类型(floatdouble)来修复此特定示例;但如果你想比较更复杂计算的结果以确保完全相等,你仍会遇到问题。

答案 1 :(得分:1)

0.01double而不是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)