众所周知计算机存储数据时是使用二进制来进行存储,那么生活中接触到的浮点数(小数)是以怎样的方式进行存储的呢?为什么小数会出现精度丢失?
现在根据我自己的理解方式来阐述一下。首先计算机所记录的信号为电信号,所以只会产生0或1。就比如数字5换算成二进制应该写做“1 0 1“。那么浮点数是否跟整数存储方式一样呢?
由图可说明小数和整数在内存的存储和读取并不相同。
其实根据IEEE(电气电子工程师学会)规定任何一个二进制浮点数(小数)v可以表示成以下形式
(-1)^S *M *2^E
其中(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
其中M表示为有效数字,M的值大于等于1,小于2.
E表示指数位数。
所以按照此规定我们重新解析上面代码:
(作者比较懒整数已经拆过就不做解析了)
5.0——>101.0 (十进制转二进制)
101.0——>1.01 * 2^2 (转化为大于等于1,小于2的有效数)
1.01 *2^2——>(-1)^0 * 1.01 *2^2 (5.0是正数所以S=0带入)
其中 S=0 , M=1.01 ,E=2。
又因为IEEE规定:(对于32位浮点数,最高位为符号位S,接着的八位为指数E,剩下的23位为有效数M)。
红色表示S,绿色表示E,棕色表示M(蓝色框表示32个比特位)。
因为M必然大于等于1,小于等于与2。这个数肯定为1.xxxxxxx。所以1在保存的时候默认舍去。在取出值的时候再加上。
至于指数E,在规则中E为无符号整数(正整数),但是指数是可以为负数的!所以IEEE规定E在存入内存时加上一个中位数127(8个字节能表示的最大数是255)所以E存入时+127
S=0
E=2+127=129=1000 0001(二进制)
M=1.01=01(舍去1)=0100 0000 0000 0000 0000 000
所以5.0在内存中应该是:
5.0——>
0 1000 0001 0100 0000 0000 0000 0000 000
换算十进制;
正好和用整数的方式打印浮点数一模一样。
浮点数的存储方式搞清楚了再来说说精度丢失的问题;
首先来举个例子3.3用二进制方式存储
3.3——>11.0100001010101……
可以发现在有效的空间根本存不完,所以会产生截断在转化时候无法找到被截断的部分所以产生了精度丢失。(个人理解)