为什么在C语言中此表达式的精度存在偏差?

问题描述

只需看看这两个相似表达式的结果即可

printf("%f",1.2f*100000000);

printf("%f",1.2f*10000000);

它将导致:

120000008.000000

12000000.000000

为什么不相等?

解决方法

您正在单精度浮点中进行算术运算。这样的数字(编码得到的有效数字)的尾数最多约为7位数字-大多数人会选择仅依靠6位数字,因为对数字进行浮点运算还会降低精度。在某些情况下,将大量计算结果合并在一起,则不精确度甚至更高。

浮点数以2为基础存储,并且某些简单的十进制数不能精确表示为有限的二进制分数。例如,以0.1为底数的10看起来像是以2为底数的:0.000110011001100110011 ...,其中结尾的“ 0011”将永远重复。同样,1.2看起来像1.001100110011 ...

所以最简单的以10为底的分数0.1是无限的二进制表示形式。

您通常不会注意到:即使使用“%f”扫描转换,输出例程也通常会四舍五入地隐藏这种情况。

因此,这里发生的是您已经在此数字上打印了足够的精度以耗尽尾数。您也可以使用1.2来完成。试试这个略有不同的程序:

 #include <stdio.h>

  int main() {
     float f0,f1,f2,f3,f4;
     f0 = 1.2f;
     f1 = 1.2f*100000000;
     f2 = 1.2f*10000000;
     f3 = 120000000.0f;
     f4 = 12000000.0f;

     printf("f0:  %.10f\n",f0);
     printf("f1:  %f\n",f1);
     printf("f2:  %f\n",f2);
     printf("f3:  %f\n",f3);
     printf("f4:  %f\n",f4);

     return 0;
 }

我的机器上的输出是:

 f0:  1.2000000477
 f1:  120000008.000000
 f2:  12000000.000000
 f3:  120000000.000000
 f4:  12000000.000000

打印足够的小数位,您也会发现数字较小时的精度极限,如输出的第一行所示。您真正遇到的是这样一个事实:您将其乘以足够大的数字,从而在打印数字的整数部分时会用尽精度。

请注意,仅写下产品不存在此问题(上例中f3的输出)。不精确性是将1.2的不精确表示形式乘以足够大的数字,从而使不精确性在数字的整数部分中可见。

请记住:计算机上典型的浮点计算是基于实数的有限近似值,而不是实际实数,并且不可避免地会产生不精确性,因此选择正确的精度与速度之间的权衡通常对于任何有趣的计算。

有些库根本不使用常规的IEEE浮点数,而是将更多的数字表示为要操纵的数字数组。当需要非常精确地操纵非常大或非常小的数量级数字时,无论CPU时间花费多少,都倾向于使用它们。因此,如果您运行旧的UN * X实用程序dc或bc,就不会看到此问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...