【BUG解决】关于BigDecimal与0的比较问题
这是一个很细小的知识点,但是很容易被忽略掉,导致系统问题,因此记录下来
问题背景
明明逻辑上看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()
相关文章:

【BUG解决】关于BigDecimal与0的比较问题
这是一个很细小的知识点,但是很容易被忽略掉,导致系统问题,因此记录下来 问题背景 明明逻辑上看a和b都不为0才会调用除法,但是系统会报错:java.lang.ArithmeticException异常: if (!a.equals(BigDecimal…...

Spring Bean 为何“难产”?攻克构造器注入的依赖与歧义
本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续! 🚀 魔都架构师 | 全网30W技术追随者🔧 大厂分布式系统/数据中台实战专家🏆 主导交易系统百万级流量调优 & 车联网平台架构&a…...
LeetCodeHot100(图论篇)
目录 图论岛屿数量题目代码 腐烂的橘子题目代码 课程表题目代码 实现 Trie (前缀树)题目代码 后续内容持续更新~~~ 图论 岛屿数量 题目 给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数…...

【Lecture01】动手开发科研智能体(WIN11系统)
1. 配置win11系统中的环境,安装管理器Choco: # Download and install Chocolatey: powershell -c "irm https://community.chocolatey.org/install.ps1|iex" # Download and install Node.js: choco install nodejs-lts --version"22&qu…...

“packageManager“: “pnpm@9.6.0“ 配置如何正确启动项目?
今天在学习开源项目的时候,在安装依赖时遇到了一个报错 yarn add pnpm9.6.0 error This projects package.json defines "packageManager": "yarnpnpm9.6.0". However the current global version of Yarn is 1.22.22.Presence of the "…...
Git Github Gitee GitLab
Git的工作流程 工作区(Workspace):电脑本地目录,即平时存放项目代码的地方 暂存区(Index/Stage):临时存放改动信息的地方 本地仓库(Repository):存放所有提交的版本数据 远程仓库(Remote):托管代码的服务器&#x…...
华为设备OSPF配置与实战指南
一、基础配置架构 sysname HUAWEI-ABR ospf 100 router-id 1.1.1.1area 0.0.0.0network 10.1.1.0 0.0.0.255 # 将接口加入区域0 interface GigabitEthernet0/0/1ospf enable 100 area 0.0.0.0 # 华为支持点分十进制区域号bandwidth-reference 10000 # 设置10Gbps参考带宽…...

Paraformer分角色语音识别-中文-通用 FunASR
https://github.com/modelscope/FunASR/blob/main/README_zh.md https://github.com/modelscope/FunASR/blob/main/model_zoo/readme_zh.md PyTorch / 2.3.0 / 3.12(ubuntu22.04) / 12.1 Paraformer分角色语音识别-中文-通用 https://www.modelscope.cn/models/iic/speech_p…...

Spitfire:Codigger 生态中的高性能、安全、分布式浏览器
Spitfire 是 Codigger 生态系统中的一款现代化浏览器,专为追求高效、隐私和分布式技术的用户设计。它结合了 Codigger 的分布式架构优势,在速度、安全性和开发者支持方面提供了独特的解决方案,同时确保用户对数据的完全控制。 1. 高性能浏览…...
vimadbgit命令
vim 全部选中 全选(高亮显示):按esc后,然后ggvG或者ggVG 全部复制:按esc后,然后ggyG 全部删除:按esc后,然后dG -----------------------------------------------------------------…...

运行shell脚本时报错/bin/bash^M: 解释器错误: 没有那个文件或目录
Windows的换行符为\r\n,而linux换行符为\n。先查看一下文件是什么格式的 :set ff --查询一下格式是什么 由于使用nodepad新建的脚本,首选项中格式设置成了windows,上传到linux中报错。 解决方法 1、nodepad中【设置》首选项】修改为unix&am…...
2506,wtl的通知事件
通知事件 最后一步,通知(连接)控件CMainDlg想要接受的浏览器控件触发的消息.连接在OnInitDialog(),断开在OnDestroy(). VC6中连接 VC6中,ATL的全局函数,AtlAdviseSinkMap()通知(连接)对话框中所有控件开始或终止发送事件到C对象. 该该函数的第一个参数是一个指向拥有事件映射…...

Shiro安全权限框架
①、添加依赖 ②、创建ini文件 获取权限相关信息可以通过数据库获取,也可以通过ini配置文件获取 ③、认证代码 public class ShiroRun{public static void main(){//初始化获取SecurityManagerIniSerucityManagerFactory factory new IniSecurityManagerFac…...

虚拟现实教育终端技术方案——基于EFISH-SCB-RK3588的全场景国产化替代
一、VR教育终端技术挑战与替代价值 实时交互性能瓶颈 赛扬N100/N150仅支持3DOF渲染(延迟>25ms),动态手势识别帧率≤15FPS,难以满足6DOF教学场景需求RK3588 Mali-G610 GPU支持6DOF空间渲染(延迟≤12ms&…...
深入理解CSS浮动:从基础原理到实际应用
深入理解CSS浮动:从基础原理到实际应用 引言 在网页设计中,CSS浮动(float)是一个历史悠久却又至关重要的概念。虽然现代布局技术如Flexbox和Grid逐渐流行,但浮动仍然在许多场景中发挥着重要作用。本文将带你深入理解…...
代码训练LeetCode(22)研究者H指数
代码训练(22)LeetCode之研究者H指数 Author: Once Day Date: 2025年6月4日 漫漫长路,才刚刚开始… 全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客 参考文章: 274. H 指数 - 力扣(LeetCode)力扣 (LeetCode) 全球极客挚爱的…...

网络安全A模块专项练习任务五解析
任务五:Linux 操作系统安全配置-1 任务环境说明: ✓ 服务器场景:LinuxServer:(开放链接) ✓ 用户名:root,密码:123456 ✓ 数据库用户名:root,密码:123456 请对服务器 LinuxServer 按要求进行相应的设置,提高服务器的安全性。 1.设置最小…...
git cli 基于远程master分支创建本地分支并切换
1、获取远程最新状态 git fetch origin2、从远程master创建本地分支并切换 git checkout -b new-branch-name origin/master或者,新版本写法 git switch -c new-branch-name origin/master3、如果要推送到远程,并建立跟踪,执行下面的命令 …...

Redis初入门
Nosql:Not-Only SQL(泛指非关系型数据库),作为关系型数据库的补充 作用:应对基于海量用户和海量数据前提下的数据处理问题 redis:C语言开发的一个开源的高性能键值对数据库 特征: 1、数据之…...

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话
1.简介 经过上一篇对Fiddler的配置后,绝大多数的Https的会话,我们可以成功捕获抓取到,但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话,需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…...

使用pandas实现合并具有共同列的两个EXCEL表
表1: 表2: 表1和表2,有共同的列“名称”,而且,表1的内容(行数)<表2的行数。 目的,根据“名称”列的对应内容,将表2列中的“所处行业”填写到表1相应的位置。 实现代…...

2025年- H69-Lc177--78.子集(回溯,组合)--Java版
1.题目描述 2.思路 3.代码实现 class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> resnew ArrayList<>();List<Integer> curnew ArrayList<>();//从索引0开始递归backtracking(res,cur,nums,0…...

目标检测任务的评估指标mAP50和mAP50-95
mAP50 和 mAP50-95 是目标检测任务中常用的评估指标,用于衡量模型在不同 交并比(IoU)阈值 下的平均精度(Average Precision, AP)。它们的区别主要体现在 IoU 阈值范围 上。 ✅ 1. mAP50(mean Average Prec…...

C++String的学习
1、C语言中的字符串 C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想(即面向对象编程(…...

java day15 (数据库)
进入数据库的学习 DB 因为数据太多了,方便统一管理的软件 操作就不用改代码了,直接改数据库则可; 命令就是sql语句 这些都是关系型数据库,sql可以控制全部,至于具体的环境我以前就有安装过了; 理解&am…...
SQL 中 IN 和 EXISTS 的区别
SQL 中 IN 和 EXISTS 的区别 1. 基本概念 1.1 IN 运算符 IN 是一个条件运算符,用于检查某个值是否存在于指定的值列表中或子查询返回的结果集中。 SELECT * FROM employees WHERE department_id IN (SELECT id FROM departments WHERE location = New York)...

多线程爬虫使用代理IP指南
多线程爬虫能有效提高工作效率,如果配合代理IP爬虫效率更上一层楼。作为常年使用爬虫做项目的人来说,选择优质的IP池子尤为重要,之前我讲过如果获取免费的代理ip搭建自己IP池,虽然免费但是IP可用率极低。 在多线程爬虫中使用代理I…...

前端面试真题(第一集)
目录标题 1、跨域问题及解决方法同源策略生产环境解决方案开发环境解决方案其他解决方案 2、组件间通信方式Vue2中的组件通信方式Vue3中的组件通信方式通用注意事项 3、微信小程序生命周期微信小程序原生生命周期UniApp生命周期 4、微信小程序授权登录流程登录流程手机号获取 5…...
电脑安装系统蓝屏的原因
1. 内存故障 原因:内存条接触不良、损坏或兼容性问题(如不同品牌 / 频率的内存混用)。表现:蓝屏代码可能包含 MEMORY_MANAGEMENT、PAGE_FAULT_IN_NONPAGED_AREA 等。排查方法: 重新插拔内存条,清理金手指灰…...

TDengine 高级功能——流计算
简介 在时序数据的处理中,经常要对原始数据进行清洗、预处理,再使用时序数据库进行长久的储存,而且经常还需要使用原始的时序数据通过计算生成新的时序数据。在传统的时序数据解决方案中,常常需要部署 Kafka、Flink 等流处理系统…...