浮点数运算结果不精确,以及用String来构造BigDecimal进行浮点数精确计算

时间:2024-08-18 17:35:02

1.浮点数运算结果不精确
 先看如下代码

         System.out.println(1.0 - 0.8);
System.out.println(0.2 + 0.1);
System.out.println(1.0 - 0.8 == 0.2); //false
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做浮点数的精确计算

         //BigDecimal构造方法参数传入String,精准
BigDecimal b2 = new BigDecimal("1.0").subtract(new BigDecimal("0.8"));
System.out.println(b2);
System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.1")).add(new BigDecimal("0.1")));
System.out.println(b2.equals(new BigDecimal(0.2))); //false
System.out.println(b2.equals(new BigDecimal("0.2"))); //true BigDecimal t2 = new BigDecimal("0.1");
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不精确。如下:

         //BigDecimal构造方法参数传入double类型,不精准
BigDecimal b = new BigDecimal(1.0).subtract(new BigDecimal(0.8));
System.out.println(b);
System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.1)).add(new BigDecimal(0.1))); BigDecimal t = new BigDecimal(0.1);
System.out.println(t);

输出结果为:

0.1999999999999999555910790149937383830547332763671875
0.3000000000000000166533453693773481063544750213623046875
0.1000000000000000055511151231257827021181583404541015625

参考:

http://superivan.iteye.com/blog/963628

http://blog.****.net/xiaoyufu007/article/details/6654010

http://www.cnblogs.com/mingforyou/p/3344489.html

https://www.zhihu.com/question/26994476