1.浮点数运算结果不精确
先看如下代码
1 System.out.println(1.0 - 0.8);
2 System.out.println(0.2 + 0.1);
3 System.out.println(1.0 - 0.8 == 0.2); //false
4 System.out.println(0.2 + 0.1 == 0.3); //false
输出结果为:
0.19999999999999996
0.30000000000000004
false
false
发现不是我们想要的正确结果,出现了1.0-0.8不等于0.2,0.2+0.1也不等于0.3的现象。
这是因为将java将double浮点数转换为64位二进制性,出现了精度损失。这跟IEEE754标准有关。可参考
https://www.iovi.com/post/2014-07-07-talk-about-double-in-java.html
2.用String来构造BigDecimal做浮点数的精确计算
1 //BigDecimal构造方法参数传入String,精准
2 BigDecimal b2 = new BigDecimal("1.0").subtract(new BigDecimal("0.8"));
3 System.out.println(b2);
4 System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.1")).add(new BigDecimal("0.1")));
5 System.out.println(b2.equals(new BigDecimal(0.2))); //false
6 System.out.println(b2.equals(new BigDecimal("0.2"))); //true
7
8 BigDecimal t2 = new BigDecimal("0.1");
9 System.out.println(t2);
输出结果为:
0.2
0.3
false
true
0.1
注意:只有用new BigDecimal(String)的构造方法,得到的才是浮点数的精确值。
以上第5行代码,用0.2这个double类型构造的BigDecimal已经丢失了精度,所以equals结果为false。
用new BigDecimal(Double)的构造方法,构造的BigDecimal不精确。如下:
1 //BigDecimal构造方法参数传入double类型,不精准
2 BigDecimal b = new BigDecimal(1.0).subtract(new BigDecimal(0.8));
3 System.out.println(b);
4 System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.1)).add(new BigDecimal(0.1)));
5
6 BigDecimal t = new BigDecimal(0.1);
7 System.out.println(t);
输出结果为:
0.1999999999999999555910790149937383830547332763671875
0.3000000000000000166533453693773481063544750213623046875
0.1000000000000000055511151231257827021181583404541015625
参考:
http://superivan.iteye.com/blog/963628
http://blog.csdn.net/xiaoyufu007/article/details/6654010
http://www.cnblogs.com/mingforyou/p/3344489.html
https://www.zhihu.com/question/26994476