为了账号安全,请及时绑定邮箱和手机立即绑定

0.1+0.2为什么等于0.3000000...4?

2020.03.18 18:26 1889浏览

最近有同学在问答区提到了一个很有意思的问题,为什么0.1+0.2 = 0.30000…4?
这个问题是怎么来的呢?有Python环境的同学,只要打开Python终端,输入0.1+0.2,就能得到0.3000000…4的结果。
图片描述
那到底这是为什么?今天就来探讨一下这个问题。

二进制

首先我们知道,计算机是以二进制的方式存储数据的,比如:5=101(2),15=1111(2),25=11001(2),把十进制转换成二进制的方式叫做重复相除法,过程大致是这样子的。

25/2 = 12.....1
12/2=6......0
6/2=3......0
3/2=1......1
1/2=0......1
# 遵循两个原则
# 1. 重复相除,直到商为0结束
# 2. 余数结果从下往上得到二进制形式

我们也可以按照按权展开法,得到二进制转换成十进制的结果,过程大致是这样子的。

11001 = 1*2^4 + 1*2^3 + 1*2^0 = 16 + 8 + 1 = 25

不过以上只是整数形式的转换方法,小数在计算机硬件上也是使用二进制表示的,不过转换的方法有些不一样,十进制小数转换成二进制的方法叫做重复相乘法

重复相乘法

一般来说如果一个小数既有整数部分又有小数部分,那么这个小数转换成二进制是分成两个部分转换的,整数部分使用重复相除法小数部分使用重复相乘法
重复相乘法的大概过程是这个样子的,比如想把十进制小数0.125转换成二进制。

0.125*2=0.25=0.25+0
0.25*2=0.5=0.5+0
0.5*2=1=0.0+1
# 注意,这里把结果分成了小于1和大于等于1的两个部分,当小于1的部分=0时,结束运算。
# 大于等于1的部分,从上往下得到001即为0.125的小数结果(0.001)。

再举一个复杂一点的例子:
图片描述

精度问题

小学我们学过,小数分为有限小数无限小数,无限小数又分为无限循环小数无限不循环小数
同样的,对于二进制小数来说,同样有有限小数和无限小数两大类。
那么重点来了,0.1和0.2在十进制小数里面是有限小数,但是使用二进制表示的时候就不是了。
不信你使用重复相乘法计算一下试试:

# 运算可以得到:
0.1=0.0001100110011...
# 它实际上是一个无限循环小数
0.1=0.0(0011) # 括号的0011即是无限循环的部分
# 同理得到0.2的二进制
0.2=0.(0011) # 括号的0011即是无限循环的部分

所以计算机是无法准确表示0.1和0.2两个数的,只能无限逼近这两个数。
假设计算机使用10位精度,则计算机里面,0.1和0.2是这样子的。

0.1=0.0001100110(2)
0.2=0.0011001100(2)
# 现在我们使用二进制加法,运算两个二进制数
0.0001100110
0.0011001100
————————
0.0100110010(2)

再把这个结果转换成十进制

0.0100110010(2) = 1*(1/4) + 1*(1/32) + 1*(1/64) + 1*(1/512) = 0.298828125 < 3

可以看到这个数值已经很接近3了,如果把精度再调高为16位、32位甚至是64位,会得到更加接近3的结果。这就解释了为什么在十进制中运算和在二进制中运算,会得到不一样的结果。
但是,这就完了吗?还没有。其实可以归纳总结到,不管精度是多少,这个结果应该是恒小于3的,而不可能是大于3的结果,因为在截取有效数时,总是把末尾的数值去掉了,那为什么在Python这里会大于3呢?
这主要是因为除了精度以外,计算机浮点数表示数据的时候还有对阶、零舍一入等等的操作,有可能会使得实际操作数比原操作数大一些。
在十进制中有四舍五入法。比如:

0.499999 约等于 0.5
0.41999 约等于 0.4

同样的,在二进制中,有零舍一入的操作。

0.1001(2) 约等于 0.10(2)
0.1011(2) 约等于 0.11(2)

所以在二进制运算中,为了进行有效数值的运算,还会对浮点数尾数进行零舍一入的操作,从而导致真实值和计算值的偏差。这就可以合理的解释在Python中0.1+0.2为什么等于0.3000…4了。
谢谢大家。

点击查看更多内容

本文原创发布于慕课网 ,转载请注明出处,谢谢合作

5人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消