python疑问2:2.25-2.2!=0.05?

对于标题疑问,2.25-2.2!=0.05,那正确答案是什么呢?spa

print(2.25-2.2) //0.04999999999999982

事实证实,的确不等于0.05.那0.04999999999999982是怎么得来的呢?
Google:由于偏差
偏差是怎么产生的,为何整数就能精确表示,而浮点数不能精确表示?
Google:由于整数和浮点数在计算机的存储方式不一样
那浮点数跟整数相比,浮点数在计算机如何存储的呢?
Google:说来话长......code

1.计算机的本质
追根究底,计算机工做的实质即是电压的高低切换,像电灯,高电位,电灯亮,低电位,电灯灭。为了表示这两种状态,便引入0和1.为了表示更多状态,便增长0和1的对数。32bit和64bit的计算机就是这样来的,表明了计算机内存存放待处理数据的大小。32bit的计算机内存大概在4G左右,64bit更多。图片

//32bit
00000000000000000000000000000000-11111111111111111111111111111111

2.浮点数存储方式
因为计算机不识别十进制,因此十进制数据都要转换为二进制保存。而且是以二进制的科学记数法进行保存内存

2.25 = 10.01(二进制) = 1.001*2^1(二进制科学计数法)
// 2.25整数部分转换:2=10(除2取余法)
// 小数部分转换过程:0.25*2 = 0.5 取整数部分0 (乘2取整法)
//                  0.5*2 = 1 取整数部分1
// 故小数部分0.25 = .01

浮点数转换为二进制科学计数法,由三部分组成符号位,指数位,尾数部分
图片描述it

这三部分在计算机中是怎么存储的呢?
以单精度float为例,float根据IEEE R32.24标准数据占32位,每部分存放规则以下:
图片描述class

说明:1.对于符号位,若值为正,则为0,若值为负,则为1
2.对于指数位,因为指数存在正指数和负指数,占一位,其他7位表示值的大小,故范围为-127~128.指数位采用移位存储方式,即元指数+127(00000000=>-127)~(11111111=>128)
3.对于尾数部分,因为第一位恒为1,因此实际表示并未考虑第一位,因此有效位为24位循环


那么2.25(即1.001*2^1)在计算机中存储方式为:二进制

0(正) 10000000(1+127) 00100000000000000000000(.001)

2.2呢?
利用十进制转二进制得:float

//2.2小数本分0.2采用乘2取整法过程:
//0.2*2=0.4    0
//0.4*2=0.8    0
//0.8*2=1.6    1
//0.6*2=1.2    1
//0.2*2=0.4    0
//......
//不可能乘2刚好获得1.0
2.2=10.00110011001100110011001100110011001100110011001101...(无限不循环)
=1.00011001100110011001100*2^1(尾数部分超过23位都被截去了) !=2.2

0(正) 10000000(1+127) 00011001100110011001100

可见,2.2的小数部分经过乘二取整法,永远没法刚好达到1,因此二进制尾数部分红无限不循环,超过23位的数据会直接被丢弃,致使与原十进制数据不相等。这也就是偏差产生的根源。im

相关文章
相关标签/搜索