BigDecimal注意事项
本文最后更新于 2024年6月18日 下午
BigDecimal注意事项
由于计算机是二进制的,在进行浮点数的存储和运算时,会出现精度丢失的风险,因此《阿里巴巴 Java 开发手册》中提到:“为了避免精度丢失,可以使用 BigDecimal
来进行浮点数的运算”。但是在使用 BigDecimal 时也会出现一些问题,下面就是一些常见的。
1. 精度丢失风险
首先我们要知道的是 BigDecimal 创建对象一般推荐使用的是静态方法 BigDecimal.valueOf(double)
和构造函数 BigDecimal(String)
《阿里巴巴 Java 开发手册》对这部分内容也有提到,如下图所示:
对于 BigDecimal 的运算方面,add
方法用于将两个 BigDecimal
对象相加,subtract
方法用于将两个 BigDecimal
对象相减。multiply
方法用于将两个 BigDecimal
对象相乘,divide
方法用于将两个 BigDecimal
对象相除。
1 |
|
这里需要注意的是,在我们使用 divide
方法的时候尽量使用 3 个参数版本,并且RoundingMode
不要选择 UNNECESSARY
,否则很可能会遇到 ArithmeticException
(无法除尽出现无限循环小数的时候),其中 scale
表示要保留几位小数,roundingMode
代表保留规则。
1 |
|
2. 等值判断问题
《阿里巴巴 Java 开发手册》中提到:浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断。因为浮点数采用 “尾数+阶码” 的编码方式,类似于科学计数法的 “有效数字+指数” 的表示方式,所以二进制无法精确表示大部分的十进制小数。
那么使用 BigDecimal 就能一劳永逸的用 equals()
来比较吗?
答案是不建议使用 equals()
来比较 BigDecimal 这是因为 equals()
方法不仅仅会比较值的大小(value)还会比较精度(scale),而 compareTo()
方法比较的时候会忽略精度。
《阿里巴巴 Java 开发手册》中提到:
compareTo()
方法可以比较两个 BigDecimal
的值,如果相等就返回 0,如果第 1 个数比第 2 个数大则返回 1,反之返回-1。
3. 设置保留几位小数
通过 setScale
方法设置保留几位小数以及保留规则。保留规则有挺多种,不需要记,IDEA 会提示。
1 |
|