【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()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908150.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

千年之后再出發,銅官窯駛入微短劇的數字航道

過去一年里,微短劇已經成為走向全民關注、平臺扶持、政策引導的“內容新主流”。從市值百億的爆款平臺到走出國門的“短劇出海”,微短劇正在重塑中國數字文化的表達方式與產業結構,也成為各地競相爭奪的“新藍海”。 就在這樣的背景下&#…

數據庫管理-第333期 Oracle 23ai:RAC打補丁完全不用停機(20250604)

數據庫管理333期 2025-06-04 數據庫管理-第333期 Oracle 23ai:RAC打補丁完全不用停機(20250604)1 概念2 要求3 操作流程4 轉移失敗處理總結 數據庫管理-第333期 Oracle 23ai:RAC打補丁完全不用停機(20250604&#xff0…

Trae CN IDE自動生成注釋功能測試與效率提升全解析

Trae CN IDE 的自動注釋功能可以通過 AI 驅動的代碼分析生成自然語言注釋,以下是具體測試方法和優勢總結: 一、Python 代碼注釋生成測試 1. 測試環境 IDE:Trae CN IDE(需確認支持 Python)代碼示例: def …

軟考 系統架構設計師系列知識點之雜項集萃(79)

接前一篇文章:軟考 系統架構設計師系列知識點之雜項集萃(78) 第141題 軟件測試一般分為兩個大類:動態測試和靜態測試。前者通過運行程序發現錯誤,包括()等方法;后者采用人工和計算機…

有公網ip但外網訪問不到怎么辦?內網IP端口映射公網連接常見問題和原因

有公網IP但外網訪問不到的核心原因通常包括:端口未正確映射、防火墻限制、DNS解析問題、運營商端口屏蔽或路由配置錯誤?。需依次排查這些關鍵環節,其中端口映射和防火墻設置是最常見的原因。?? ?內網IP端口映射公網連接常見問題和原因及解決方案 1…

HttpServletResponse 對象用來做什么?

HttpServletResponse 對象是由 Servlet 容器創建并傳遞給 Servlet 的 service() 方法(以及間接傳遞給 doGet(), doPost() 等方法)的。它的核心作用是讓 Servlet 能夠向客戶端(通常是瀏覽器)發送 HTTP 響應。 通過 HttpServletRes…

FTPS、HTTPS、SMTPS以及WebSockets over TLS的概念及其應用場景

一、什么是FTPS? FTPS,英文全稱File Transfer Protocol with support for Transport Layer Security (SSL/TLS),安全文件傳輸協議,是一種對常用的文件傳輸協議(FTP)添加傳輸層安全(TLS)和安全套接層(SSL)加密協議支持的擴展協議。…

前端??HTML contenteditable 屬性使用指南

??什么是 contenteditable? HTML5 提供的全局屬性,使元素內容可編輯類似于簡易富文本編輯器兼容性?? 支持所有現代瀏覽器(Chrome、Firefox、Safari、Edge) 移動端(iOS/Android)部分鍵盤行為需測試 &l…

持續領跑中國異地組網路由器市場,貝銳蒲公英再次登頂銷量榜首

作為國產遠程連接SaaS服務的創領者,貝銳持續引領行業發展,旗下貝銳蒲公英異地組網路由器,憑借出色的技術實力和市場表現,斬獲2024年線上電商平臺市場銷量份額中國第一的佳績,充分彰顯了其在網絡解決方案與異地組網領域…

五大主流大模型推理引擎深度解析:llama.cpp、vLLM、SGLang、DeepSpeed和Unsloth的終極選擇指南

在人工智能的競技場上,大模型推理框架就像是為超級跑車精心調校的引擎系統——選對了能讓你的AI應用一騎絕塵,選錯了可能連"停車場"都開不出去。這些框架的核心價值在于將訓練好的"大腦"轉化為實際可用的"肌肉記憶",而選擇標準則需要像職業賽…

前端面試二之運算符與表達式

目錄 1.JavaScript 中的 和 運算符 2.|| (邏輯或) 運算符 與 ES6 默認參數的區別 與 ?? (空值合并運算符) 的區別 3.?.(可選鏈)運算符 (1). 安全訪問深層嵌套屬性 (2). 安全調用可能不存在的函數 (3). 安全訪問數組元素 4.展開運算符 (..…

GB/T 24507-2020 浸漬紙層壓實木復合地板檢測

浸漬紙層壓實木地板是指以一層或多層專用紙浸漬熱固性氨基樹脂,經干燥后鋪裝在膠合板基材正面,專用紙表面加耐磨層,基材背面可加平衡層,經熱壓、成型的地板。 GB/T 24507-2020 浸漬紙層壓實木復合地板測試項目: 測試項…

AWS DocumentDB vs MongoDB:數據庫的技術抉擇

隨著非關系型數據庫在現代應用中的廣泛應用,文檔型數據庫因其靈活的結構與出色的擴展性,逐漸成為企業開發與架構設計中的核心選擇。在眾多文檔數據庫中,MongoDB 憑借其成熟生態與社區支持占據主導地位;與此同時,AWS 提…

微信小程序實現運動能耗計算

微信小程序實現運動能耗計算 近我做了一個挺有意思的微信小程序,能夠實現運動能耗的計算。只需要輸入性別、年齡、體重、運動時長和運動類型這些信息,就能算出對應的消耗熱量。 具體來說,在小程序里,性別不同,身體基…

三軸地磁傳感器的主要應用場景

隨著材料科學、微電子技術以及傳感器技術的不斷進步,三軸地磁傳感器的性能將不斷提升,包括提高精度、降低功耗、增強抗干擾能力等。 RAMSUN提供的是一款三軸地磁傳感器采用第三代AMR技術,帶有自動溫度補償的三軸磁傳感器,該產品因…

使用 SseEmitter 實現 Spring Boot 后端的流式傳輸和前端的數據接收

1.普通文本消息的發送和接收 GetMapping("/stream")public SseEmitter streamResponse() {SseEmitter emitter new SseEmitter(0L); // 0L 表示永不超時Executors.newSingleThreadExecutor().execute(() -> {try {for (int i 1; i < 5; i) {emitter.send(&q…

nssm配置springboot項目環境,注冊為windows服務

NSSM 的官方下載地址是&#xff1a;NSSM - the Non-Sucking Service Manager1 使用powershell輸入命令,java項目需要手動配置和依賴nacos .\nssm.exe install cyMinio "D:\minio\啟動命令.bat" .\nssm.exe install cyNacos "D:\IdeaProject\capacity\nacos-s…

WinCC學習系列-基礎概念

從本節起&#xff0c;學習和了解西門子最新SCADA軟件WinCC 8.0&#xff0c;將從基礎概念開始&#xff0c;到入門操作&#xff08;創建項目、組態通信、組態過程畫面、組態面板類型和變量結構、歸檔和顯示值、組態消息&#xff09;&#xff0c;到高級應用&#xff08;WinCC選件、…

數據分析圖表類型及其應用場景

說明&#xff1a;頂部HTML文件下載后可以直接查看&#xff0c;帶有示圖。 摘要 數據可視化作為現代數據分析的核心環節&#xff0c;旨在將復雜、抽象的數據轉化為直觀、易懂的圖形形式。這種轉化顯著提升了業務決策能力&#xff0c;優化了銷售與營銷活動&#xff0c;開辟了新…

《江西棒壘球》敗方mvp叫什么·棒球1號位

敗方mvp也是MVP&#xff0c;以棒球運動為例&#xff0c;MLB&#xff08;美國職棒大聯盟&#xff09;的個人獎項旨在表彰球員在不同領域的卓越表現&#xff0c;涵蓋常規賽和季后賽的杰出成就。 常規賽核心獎項 最有價值球員獎&#xff08;MVP&#xff09; 定義&#xff1a;表彰…