创建qq网站吗,郑州华久做网站,企业vi设计公司旅游公司logo,wordpress 爱奇艺插件下载失败这是一个很细小的知识点#xff0c;但是很容易被忽略掉#xff0c;导致系统问题#xff0c;因此记录下来
问题背景
明明逻辑上看a和b都不为0才会调用除法#xff0c;但是系统会报错#xff1a;java.lang.ArithmeticException异常#xff1a;
if (!a.equals(BigDecimal…这是一个很细小的知识点但是很容易被忽略掉导致系统问题因此记录下来
问题背景
明明逻辑上看a和b都不为0才会调用除法但是系统会报错java.lang.ArithmeticException异常
if (!a.equals(BigDecimal.ZERO) !b.equals(BigDecimal.ZERO)) {BigDecimal divide a.divide(b, 2, RoundingMode.HALF_UP);
}异常截图
分析
说明 a.equals(BigDecimal.ZERO)和 b.equals(BigDecimal.ZERO)同时为false但是能引起java.lang.ArithmeticException异常的b为0所以 b.equals(BigDecimal.ZERO)的判断有误
然后就考虑到如果b的精度不是0而是0.00那么 b.equals(BigDecimal.ZERO)是不是会为false
在 Java 中BigDecimal 的 equals 方法比较的是值及其精度。
这是因为 BigDecimal.ZERO 表示的数字是 0, 精度scale为 0即没有小数部分。而 0.00 的精度则为 2所以它们被认为是不同的对象。以下是示例代码
BigDecimal b new BigDecimal(0.00);
System.out.println(b.equals(BigDecimal.ZERO)); // 输出: false如果想检查一个 BigDecimal 是否为零而不关心精度使用 compareTo 方法如下所示
if (b.compareTo(BigDecimal.ZERO) 0) {System.out.println(b 是零);
} else {System.out.println(b 不是零);
}使用 compareTo 方法可以比较值而不考虑精度这样对于 0.00 和 0 的比较都是等于零的。
源码分析
这里我们对equals和compareTo的源码进行分析
(1) BigDecimal.equals() 的实现会比较数值和精度(scale)
public boolean equals(Object x) {if (!(x instanceof BigDecimal))return false;BigDecimal xDec (BigDecimal) x;if (x this)return true;if (scale ! xDec.scale) // 精度比较return false;long s this.intCompact;long xs xDec.intCompact;if (s ! INFLATED) {if (xs INFLATED)xs compactValFor(xDec.intVal);return (xs s);} else if (xs ! INFLATED)return compactValFor(this.intVal) xs;return this.inflated().equals(xDec.inflated());
}关键点 首先比较精度(scale)如果不相同直接返回false 然后比较数值本身 所以 new BigDecimal(0.00).equals(BigDecimal.ZERO) 会返回false因为精度不同(2 vs 0)
(2) compareTo 方法源码分析 BigDecimal.compareTo() 的实现
public int compareTo(BigDecimal val) {// Quick path for equal scale and non-inflated caseif (scale val.scale) {long xs intCompact;long ys val.intCompact;if (xs ! INFLATED ys ! INFLATED)return xs ! ys ? ((xs ys) ? 1 : -1) : 0;}int xsign this.signum();int ysign val.signum();if (xsign ! ysign)return (xsign ysign) ? 1 : -1;if (xsign 0)return 0;int cmp compareMagnitude(val);return (xsign 0) ? cmp : -cmp;
}首先会比较符号(signum) 然后使用 compareMagnitude 比较绝对值 不直接比较精度(scale)而是会统一调整后再比较 new BigDecimal(0.00).compareTo(BigDecimal.ZERO) 会返回0因为数值相同
最佳实践 当需要严格比较两个BigDecimal是否完全相同时包括精度使用 equals() 当只需要比较数值大小时使用 compareTo() 检查是否为0时推荐使用 compareTo()