import java.math.*;
public class DoubleTest{
public static void main(String args[]){
System.out.println(4.015*100);
System.out.println("BigDecimal:"+(BigDecimal.valueOf(4.015)).multiply(BigDecimal.valueOf(100)));
}
}
结果为:401.49999999999994
BigDecimal:401.500
在程序中单纯的用float 或 double 来进行多次计算很有可能出现上述问题,可是为什么会出现此问题呢?
原因是浮点数的表示是用二进制表示的,其中float占4字节(有效数字6-7位),double占8字节(有效数字15位)。
浮点数结构(float/double)
符号位(S):1bit | 指数位(E):8bit |
尾数位(M):23bit
|
符号位(S):1bit | 指数位(E):11bit | 尾数位(M):52bit |
float的尾数:23位,其范围为:0~ 223 ,而 223=8388608=106.92 ,所以float的精度为6~7位,能保证6位为绝对精确,7位一般也是正确的.
double的尾数:52位, 2−52 =2.220446049250313E-16,最小是16位,但最小不是1.0E-16,所以精度是15~16,能保证15,一般16位。
不理解的话,可以再这样想:folat 尾数位23位,二进制0101……0101,尾数表示小数位,最小为0000……0001(22个0,最后一个1),即 2−23 =1.1920929E-7 ,这是float的最小单元(大概是0.0000001192大小,你想表示比这更小的,比如0.00000001,不可能啊),这是一个7位小数位小数,最小就是这么小,比这个更小的,计算机就无能为力了,比这个更大的,每次通过加这么一个最小单元,直到相等或接近(两个相差一个最小单元的数,它们之间的数也是不能表示的,所以有的7位也是不能精确的,因为最小不是0.0000001,而是比这个稍大)。