浮点数表示误差详解
1. 存储结构
计算机存储浮点数采用IEEE754标准,其结构为:
数符s:0表示该数为正,1表示该数为负。占1bit大小。
阶码e:采用移码表示,即加上了一个固定的偏移。阶码全为1表示无穷大。
尾数f:尾数数值最高位1被隐藏,所以实际的尾数数值为1.f。在将数转为浮点数时,小数点左边也就必须是1的这种形式。
真值的计算方法为:val = s * 1.f * 2e-offset
float类型的最大数值为:1.111...11 X 2127 = 1.89045759400... * 1038
2. 浮点数表示产生误差原因
a. 由于计算百机内部以二进制保存,所以十进制的有限位的小数,在计算机内部会是一个无限位的小数。
例如: 十进制的0.9虽然只有一位小数,转成2进制道是无限循环小数0.1110011001100110011...
b. 计算机保存浮点数的精度有限,例如float可以保留十进制最多7位(二进制23位)有效数字,
double可以保留十进制15-16位(二进制52位)有效数字。那有效数字以后的位就被忽略了。
例如:0.9的表示受精度所限,精度以后的就被忽略了,这样
float时,它是0.89999998
double时,它是0.90000000000000002
即:除了可以表示为2的幂次以及整数数乘的浮点数可以准确表示外,其余的数的值都是近似值。
3. 舍入方法
既然十进制的有限位小数,在计算机内部可能是一个无限位小数,那就存在舍入策略。
假定经过运算后的数共有p+q位,现仅允许保留前p位。舍入方法有许多种,常见的舍入方法有:
a. 恒舍(切断):多余部分q位一律舍去,保留部分的p位不作任何改变。
b. 恒置1法:即不论多余部分q位为何代码,都把保留部分p位的最低位置1。
c. 下舍上入法:即0舍1入,相当于十进制中的四舍五入。用将要舍去的q位的最高位作为判断标志,以决定保留部分是否加1。
如该位为0,则舍去整个q位(相当于恒舍)。如该位为1,则在保留的p位的最低位上加1。
4. 浮点数的比较
浮点数比较的时候需要用一个很小的数值来进行比较。当二者之差小于这个很小的数时,就认为二者是相等的了。
而不能直接用== 或!=比较。这个很小的数,称为精度。
精度由计算过程中需求而定。比如一个常用的精度为1e-6.也就是0.000001.
所以对于两个浮点数a,b,如果要比较大小,那么常常会设置一个精度。
a. 判断等于的时候,就是:if(fabs(a-b) <= 1e-6)。fabs是求浮点数绝对值的函数。
b. 判断大于的时候,就是:if(a > b && fabs(a-b) > 1e-6)。
c. 判断小于的时候,就是:if(a < b && fabs(a-b) > 1e-6)。