两个花车的划分给出了错误的答案

时间:2015-08-25 13:15:25

标签: c gcc division

尝试使用以下代码在C中划分两个浮点数:

#include <stdio.h>
#include <math.h>

int main(){
  float fpfd = 122.88e6;
  float flo = 10e10;
  float int_part, frac_part;

  int_part = (int)(flo/fpfd);
  frac_part = (flo/fpfd) - int_part;

  printf("\nInt_Part = %f\n", int_part);
  printf("Frac_Part = %f\n", frac_part);

  return(0);
}

对于此代码,我使用命令:

>> gcc test_prog.c -o test_prog -lm
>> ./test_prog

然后我得到了这个输出:

Int_Part = 813.000000
Frac_Part = 0.802063

现在,这个Frac_part似乎不正确。我先在计算器上尝试了相同的等式,然后在Wolfram Alpha中尝试了相同的等式,他们都给了我:

Frac_Part = 0.802083

请注意,小数点后五位的数字不同。

这对大多数人来说似乎微不足道,但对于我所做的计算来说,这是至关重要的。

任何人都可以向我解释为什么C代码会出现此错误吗?

3 个答案:

答案 0 :(得分:5)

当浮点运算的精度不足时,第一个最自然的步骤就是使用更高精度的浮点类型,例如:使用double代替float。 (正如其他答案中所指出的那样。)

其次,检查不同的浮点运算并考虑它们的精度。作为错误来源的突出的一个方法是上面的方法,通过简单地转换为int和减去将float分成整数部分和小数部分。这并不理想,因为当你从原始值中减去整数部分时,你正在进行算术,其中涉及的三个数字(两个输入和结果)具有非常不同的比例,这可能会导致精度损失。

我建议使用C <math.h>函数modf来将浮点数分成整数和小数部分。 http://www.techonthenet.com/c_language/standard_library_functions/math_h/modf.php

(更详细:当你执行像f - (int)f这样的操作时,浮点加法过程将会看到添加了两个给定精度X的数字,并且它会自然地假设结果也将具有精度X.然后它将在该假设下执行实际计算,并最终在结束时重新评估结果的精度。因为初始预测结果不理想,所以一些低阶位将丢失。 )

答案 1 :(得分:3)

Float是浮点数的单精度,你应该尝试使用double,下面的代码给出了正确的结果:

#include <stdio.h>
#include <math.h>

int main(){
  double fpfd = 122.88e6;
  double flo = 10e10;
  double int_part, frac_part;

  int_part = (int)(flo/fpfd);
  frac_part = (flo/fpfd) - int_part;

  printf("\nInt_Part = %f\n", int_part);
  printf("Frac_Part = %f\n", frac_part);

  return(0);
}

为什么?

正如我所说,float是单精度浮点数,它们小于double(在大多数架构中,sizeof(float) < sizeof(double))。 使用double代替float,您将有更多位来存储尾数和数字的指数部分(请参阅wikipedia)。

答案 2 :(得分:2)

float只有6~9位有效数字,对于大多数实际使用来说,它不够精确。将所有float变量更改为double(提供15~17位有效数字)可得出输出:

Int_Part = 813.000000
Frac_Part = 0.802083
相关问题