对于标题疑问,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