java float double为什么精度会丢失
由于对float或double?的使用不当,可能会出现精度丢失的问题。问题大概情况可以通过如下代码理解:
?
public class FloatDouble{public static void main(String[] args){double d = 8;long l = Double.doubleToLongBits(d);System.out.println(Long.toBinaryString(l));float f = 8;int i = Float.floatToIntBits(f);System.out.println(Integer.toBinaryString(i));}}??
输出结果如下:
?
Double:100000000100000000000000000000000000000000000000000000000000000
Float:1000001000000000000000000000000
对于输出结果分析如下。对于都不?double?的二进制左边补上符号位?0?刚好可以得到?64?位的二进制数。根据double的表 示法,分为符号数、幂指数和尾数三个部分如下:
0?10000010111?0011000101100111100101110000000000000000000000000000
对于?float?左边补上符 号位?0?刚好可以得到?32?位的二进制数。?根据float的表示法,?也分为?符号数、幂指数和尾数三个部分如下?:
0?10010111?00110001011001111001100
绿色部分是符号位,红色部分是幂指数,蓝色部分是尾数。
对比可以得出:符号位都是?0?,幂指数为移码表示,两者刚好也相等。唯一不同的是尾数。
在?double?的尾数 为:?001100010110011110010111?0000000000000000000000000000?,省略后面的零,至少需要24位才能正确表示?。
而在?float?下面尾数 为:?00110001011001111001100?,共?23?位。
为什么会这样?原因很明显,因为?float尾数?最多只能表示?23?位,所以?24?位的?001100010110011110010111?在?float?下面经过四舍五入变成了?23?位的?00110001011001111001100?。所以?20014999?在?float?下面变成了?20015000?。
也就是说?20014999?虽然是在float的表示范围之内,但?在?IEEE 754?的?float?表示法精度长度没有办法表示出?20014999?,而只能通过四舍五入得到一个近似值。总结:
浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是 因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用?float?和?double?作精确运 算的时候要特别小心。
可以考虑采用一些替代方案来实现。如通过?String?结合?BigDecimal?或 者通过使用?long?类型来转换。?
?
?
?
?