浮点数产生误差的根源

文章探讨了浮点数在计算机中的精度问题,指出浮点数精度并非固定,而是由十进制到二进制转化过程中的分数表达限制导致。特别分析了0.1等非纯分母2的幂数在转化时产生的无限循环误差。
摘要由CSDN通过智能技术生成

一、浮点数的精度

double型浮点数能精确到多少位小数?

试试就知道了!

#include<stdio.h>

int main(){

    printf("%.20f\n",0.5);

    printf("%.20f\n",0.25);

    printf("%.20f\n",0.1);

    printf("%.20f\n",0.3);

    printf("%.20f\n",0.7);

    return 0;

}

输出结果如下:

可见,它的精度并不是固定的。

二、浮点数产生误差的原因

浮点数的精度取决于要表示的具体值。

这个问题涉及到数在计算中的表示机制。虽然我们在代码中输入的是十进制数,但归根到底其在计算机内是以二进制存储的。计算机先要把我们输入的十进制数转化为二进制数,存储在内存中。当我们要输出时,它再把二制数转化为十进制数。

在转化的过程中,就会产生误差。更具体来说,它是产生在十进制转化为二进制这一过程中。

要弄清这一点,咱们首先要知道小数的实际意义,它表示的是几分之几,也就是“份数”。

比如我们知道0.25的分数是1/4,但这只是它的简写形式,它在十进制中的本质含义是这样的:

0.25=2/10+5/100

用文字描述,它表示10份中的2份加上100份中的5份。如果用饼表示,它表示把一张饼平均分成10份,取其中的2份,放在盘子里,再把同样一张饼平均分成100分,取其中的5份,放在盘子里,现在盘子里的饼就是2/10+5/100=0.25。

也就是说,在十进制小数中,其本质意义是,把一样东西分成10份、100份、1000份……,分别从中取0-9份凑到一块儿。它表现为分母为10的幂的分数的和,用代数式表示如下:

的值为整数0-9)

合并同类项后可以写成:

同理,在二进制小数中,其本质意义是,把一样东西分成2份、4份、8份……,分别从中取0-1份凑到一块儿。它表现为分母为2的幂的分数的和,用代数式表示如下:

的值为整数0、1)

合并同类项后可以写成:

比如0.101表示把一张饼平均分成2份,取其中的1份,放在盘子里,再把同样一张饼平均分成4分,取其中的0份,放在盘子里,再把同样一张饼平均分成8分,取其中的1份,放在盘子里,最后盘子里的数就是0.101。

这其实就是二进制小数转十进制的方法。

明白了小数的真实意义,十进制转二进制会产生误差就很好理解了。

因为份中的几份不一定能转化为份中的几份,即形如的数不一定能转为形如的数。

比如本文开头代码中测试的数:

0.5=5/10=1/2,0.25=25/100=1/4

这两个数都能转化为份中的几份,因此它们在转化为二进制时是不会产生误差的。也就是的十进制小数都不会产生浮点数误差。

因为:

所以这个数的小数部分必然是5的倍数,故这个结论也可以描述为:最后一位小数是5的十进制小数都不会产生浮点数误差,比如:0.125、0.375都不会产生误差。

反观0.1、0.3、0.7这样的数呢?拿最简单的小数0.1转化为二进制演示一下:

小数点后第1位:1/10<1/2(不到2份中的1份)→0

小数点后第2位:1/10<1/4(不到4份中的1份)→0

小数点后第3位:1/10<1/8(不到8份中的1份)→0

小数点后第4位:1/10>1/16(超过16份中的1份)→1

小数点后第5位:(1/10-1/16)=6/160>1/32(超过32份中的1份)→1

小数点后第6位:(6/160-1/32)=1/160<1/64(不到64份中的1份)→0

小数点后第7位:1/160<1/128(不到128份中的1份)→0

小数点后第8位:1/160>1/256(超过256份中的1份)→1

小数点后第9位:(1/160-1/256)=6/2560>1/512(超过512份中的1份)→1

这个式子永远找不到等号,最终的二进制数是这样一个无限循环小数:0.00011001100110011...

所以,像0.1、0.3、0.7这样无法写成形式的数,永远都无法分为 这样的分数的和,只能无穷无尽的往下分,分到山无棱、江水为竭。计算机对此情景表示很无奈,只好拦腰一刀砍下,保留前面一部分,这就产生了误差。

相反,二进制转十进制却不存在误差问题,因为任何一个都可以通过分子分母同时乘以转换为

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金创想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值