微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决为什么在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,就不会看到此问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。