Java BigDecimal解決double精度丟失的問題
我們在日常開發(fā)中, 有很多時候會遇到小數(shù)(double類型)精確計算, 由于 double 類型在計算機中的特殊存儲方式, 某些情況下會導致精度丟失, 特別是跟錢有關的計算, 后臺校驗的時候, 那得是分毫不差.
場景
商品a價格是 0.1, 商品b 價格是 0.2, 用戶買了這兩個商品, 付款時, 訂單總金額是 0.3, 如果用 double 類型做計算, 將會得到結果 0.30000000000000004, 前端如果拿來展示總金額, 用戶肯定就蒙圈了, 這顯然不是我們想要的.
那么如何解決呢? Java 給我們提供了專門解決這個問題的類 BigDecimal.
double a = 0.1; double b = 0.2; double c = a + b; System.out.println(c); // 0.30000000000000004
BigDecimal 使用
創(chuàng)建 BigDecimal 對象
創(chuàng)建對象一共有3種方式, 兩個構造器, 一個靜態(tài)方法, 實際靜態(tài)方法是對入?yún)?String 的構造器的封裝, 即 2, 3 兩種方式本質上是一樣的.
// 1 入?yún)⑹?double
BigDecimal a = new BigDecimal(0.3);
// 2 入?yún)⑹?String
BigDecimal b = new BigDecimal("0.3");
// 3 靜態(tài)方法, 入?yún)⑹?double
BigDecimal c = BigDecimal.valueOf(0.3);計算操作
公用代碼
double a = 0.1; double b = 0.2; BigDecimal a1 = BigDecimal.valueOf(a); BigDecimal b1 = new BigDecimal(Double.toString(b));
1. 加法 add
這就很好的解決了上面場景中出現(xiàn)的問題
BigDecimal c1 = a1.add(b1); System.out.println(c1); // 0.3
2. 減法 subtract
BigDecimal c2 = a1.subtract(b1); // 減法 System.out.println(c2); // -0.1
3. 乘法
BigDecimal c3 = a1.multiply(b1); // 乘法 System.out.println(c3); // 0.02
4. 除法
BigDecimal c4 = a1.divide(b1); // 除法 0.1 / 0.3, 無法除盡, 報錯. System.out.println(c4); // 0.5 BigDecimal c5 = a1.divide(c1); // 除法 System.out.println(c5); // 0.1 / 0.3, 無法除盡, 報錯. c5 = a1.divide(c1, 2, RoundingMode.HALF_UP); // 除法 0.1 / 0.3 四舍五入 System.out.println(c5); // 0.5
注意:
BigDecimal 進行除法計算時, 強烈建議使用指定保留小數(shù)倍數(shù)和舍入模式這個方法, 這樣可以避免除不盡造成的異常.
/** * 參數(shù)1: 除數(shù) * 參數(shù)2: 保留小數(shù)的位數(shù) * 參數(shù)3: 舍入模式 */ public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
5. 保留小數(shù)和舍入模式
設置保留小數(shù)和舍入模式 setScale 方法
BigDecimal price = new BigDecimal("9.936");
price = price.setScale(2, RoundingMode.HALF_UP); // 2位, 四舍五入
System.out.println(price); // 9.946. BigDecimal 轉化為 double
double value = c4.doubleValue();
總結
使用 BigDecimal 計算時要注意以下幾點:
- 不建議使用入?yún)⑹?double 的構造器, 因為它仍然存在精度問題.
- 強烈建議使用入?yún)⑹?string 的構造器, 或者使用靜態(tài)方法 valueOf 創(chuàng)建對象, 才能保證精度.
- 使用 BigDecimal 做 除法 時, 必須要使用 divide(BigDecimal divisor, int scale, RoundingMode roundingMode), 防止除不盡造成異常.
到此這篇關于Java BigDecimal解決double精度丟失的問題的文章就介紹到這了,更多相關Java BigDecimal double精度丟失內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IDEA中在啟動 SpringBoot項目時加參數(shù)的方法步驟
我們經常需要在啟動 Spring Boot 項目的時候,臨時修改一些參數(shù),例如 端口號、運行環(huán)境(profile)、日志級別 等等,除了在 application.yml 文件里修改,我們還可以通過在 IDEA 啟動配置中添加參數(shù)的方式來實現(xiàn),下面就來介紹一下2025-12-12
Apache Commons Math3探索之快速傅立葉變換代碼示例
這篇文章主要介紹了Apache Commons Math3探索之快速傅立葉變換代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-10-10
MyBatis中的collection兩種使用方法及效率比較
collection主要是應對表關系是一對多的情況,本文主要介紹了MyBatis中的collection兩種使用方法及效率比較,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06

