栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java常见错误总结】BigDecimal使用的注意点

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java常见错误总结】BigDecimal使用的注意点

先来看一个常见的问题

打印下面这两个计算结果,得到的值可能和你预期的并不一样

 System.out.println(0.1 + 0.2);
 System.out.println(1.0 - 0.8);

结果

0.30000000000000004
0.19999999999999996

之所以造成这种问题的主要原因就在于计算机无法精确表达某些数值,因此在涉及到金额计算的时,我们一般会使用BigDecimal来替代,不过它也存在一些需要特别注意的地方,否则一样会遇到一些令人匪夷所思的现象。

问题一:使用字符串类型的构造方法

如果你使用double类型的构造方法做计算,同样存在精度问题

System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.2)));

结果

0.3000000000000000166533453693773481063544750213623046875

请使用字符串类型的构造方法

 System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2")));

结果

0.3
问题二:精度取舍方式

看出来了没,随着不同的参数值,其精度结果也不同

System.out.println(new BigDecimal("1.1").multiply(new BigDecimal("100")));
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal("100")));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal("100")));
System.out.println("==================");
System.out.println(new BigDecimal("1.1").multiply(new BigDecimal(Double.toString(100))));
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal(Double.toString(100))));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal(Double.toString(100))));

结果

110.0
111.00
111.100
==================
110.00
111.000
111.1000

实际上这是因为scale和precision的原因,scale表示小数点之后的位数,precision表示精度,计算过程中传入不同的数值会直接影响scale和precision的数值,所以建议在计算时一定要显示的指定好期望的返回结果。

保留3位小数,剩下的直接舍弃

System.out.println(new BigDecimal("1.11").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.1111").multiply(new BigDecimal("10")).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println("==================");
System.out.println(new BigDecimal("1.11").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.111").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));
System.out.println(new BigDecimal("1.1111").multiply(new BigDecimal(Double.toString(10))).setScale(3, BigDecimal.ROUND_DOWN));

结果

11.100
11.110
11.111
==================
11.100
11.110
11.111
问题三:比较

如果使用equals来进行比较,可能也得不到想要的结果,比如像下面这样,返回结果为false

System.out.println(new BigDecimal("1.0").equals(new BigDecimal("1")));

看看BigDecimal提供的equals方法说明就清楚了,它除了比较value,还会比较scale

Compares this {@code BigDecimal} with the specified
{@code Object} for equality.  Unlike {@link
#compareTo(BigDecimal) compareTo}, this method considers two
{@code BigDecimal} objects equal only if they are equal in
value and scale (thus 2.0 is not equal to 2.00 when compared by
this method).

因此,如果我们只是希望比较value,则建议使用comparTo方法,其返回结果按照标准约定来,-1、0、1分别代表小于、等于、大于

System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1")));
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/749286.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号