为什么说浮点数缺乏精确性? python中浮点数运算问题

问题描述中很清楚,0.1+0.1+0.1-0.3没有得到结果0,而是溢出了(Python3.6中不会)。数字在计算机中都是用二进制保存的,那就应该用二进制解释一下。

数字的二进制

我们目前使用的数字都是十进制,方便理解和运算;计算机的底层电路是用与或非电路设计的。它只能识别二进制,所以计算机中的数字用二进制来表示。(数字在计算机中以补码形式保存,但以下内容用原码解释,容易理解)

整数二进制:01010101

  1. 位置数:右边为低位,末位记为0位;左边为高位,从右向左依次增加1。
  2. 每位的数字只能是0或1,每位代表的大小为该位的数字*2的N次方,N是位置数。若每一位的数字都是1,则从右到左每位表示的大小为1,2,4,8,…,2^N,依次扩大二倍。
  3. 二进制数字代表的大小为:对每一位二进制代表的大小进行求和
  4. 举例:7的二进制是0111,12的二进制是1100等

浮点数二进制:01010101.01010101

  1. 浮点数同样用二进制保存。整数部分和整数二进制相同,小数部分原理相同
  2. 小数部分:0位是1能代表python 列表溢出 python整数溢出_知乎,小数点后第一位是1则能够代表python 列表溢出 python整数溢出_知乎_02,小数点后第二位是1能够代表python 列表溢出 python整数溢出_Python_03,依次缩小2倍,原理同整数。

【问题1】二进制转为十进制数很简单,那么十进制如何转为二进制呢?

# 整数求二进制
# 1.每次除以2,记下商和余数(以后用上一次的商除以2)
# 2.直到某次商等于0结束 
# 3.把余数倒序书写
12/2=6...0
6/2=3...0
3/2=1...1
1/2=0...1
以12为例,二进制为1100

# 小数求二进制
# 1.每次乘以2,记下结果,并把整数和小数部分分离。(以后用上一次的小数部分乘以2)
# 2.直到某次小数部分为0结束 
# 3.把整数部分正序书写
0.625*2=1+0.25
0.25*2=0+0.5
0.5*2=1+0.0
以0.625为例,二进制为0.101
0.4*2=0+0.8
0.8*2=1+0.6
0.6*2=1+0.2
0.2*2=0+0.4
0.4*2=0+0.8
...
以0.4为例,它无法结束,二进制为0.01100110...

【问题2】回到知乎问题,为什么说浮点数缺乏精确性,结果会溢出?

  • 答:如上题所述,0.4的二进制表示是无限循环,所以如果要精确表示0.4,计算机需要无限个二进制位才能做到。然而计算机的内存、CPU寄存器等等硬件单元都是有限的,只能表示有限的二进制位。总结一句话,浮点数缺乏精确性是实数的无限精度跟计算机的有限内存之间的矛盾。

P.S. 浮点数在计算机中是以科学记数法表示的:a*10^n,a是底数,n是指数。以64位双精度为例,底数占52位,指数占11位,另外还有1位符号位,因此浮点值只有52位的精度,所以会出现舍入错误。


参考资料:

  1. 为什么说浮点数缺乏精确性? python中浮点数运算问题
  2. 为什么说浮点数缺乏精确性? python中浮点数运算问题
  3. 为什么说浮点数缺乏精确性? python中浮点数运算问题