浮点数存在精度问题主要是由于小数二进制化的逻辑与整数二进制化不一样。
整数二进制化:除二取余。
如:7的二进制为:00000111。
小数二进制化:乘二取整数。
如:0.75的二进制为:0.11 即 0.75 = 0.5+0.25 = 2^(-1) + 2^(-2)
由此,浮点数7.75的二进制形式为:111.11。
IEEE浮点结构:
符号位 + 指数 + 尾数
符号位1bit,指数e比特,尾数k比特。
float: e = 8 , k = 23.
double: e = 11 , k = 52.
浮点数二进制化过程:
a. 整数部分二进制化, 小数部分二进制化,串联起整数与小数部分。
b. 整数部分二进制位数为p(最高位为1,舍去高位的0),则指数的值= 2^(e-1) +p-1。
c. 将a中串联得到的二进制串去掉最高位的1,然后截取k位,填充到尾数中去。截取时,最后一位需要根据浮点数舍入规则进行处理,舍入规则见下面。
d. 符号位根据实际数据的符号而定,0-正数,1-负数。
对于小数0.2,不管乘以多少个2,结果都有小数部分,即无法用有限二进制来表示浮点数0.2。因此也可以推导出浮点数并不能表示所有的小数,而是只能表示间隔相同的小数序列(间隔大小与浮点数二进制位数有关系)。
那对于0.2这个数,二进制化后,实际的值是多少呢?这就需要引入另外一个概念:浮点数舍入规则。
IEEE给出的舍入规则:
a. 舍入到最近,在接近一样的情况下,优先舍入到偶数,即低位为0。 --默认舍入方式。
b. 向正无穷舍入。
c. 向负无穷舍入。
d. 向0舍入。
默认舍入举例:
//输入到四位
1.0011010 > 1.0011 ->取最近的
1.0011101 > 1.0100 ->取最近的
1.0011100 > 1.0100 ->舍入,得到偶数
1.0010101 > 1.0011 ->去最近的