Java BigDecimal解決double精度丟失的問題
我們在日常開發(fā)中, 有很多時候會遇到小數(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)方法是對入參 String 的構造器的封裝, 即 2, 3 兩種方式本質上是一樣的.
// 1 入參是 double BigDecimal a = new BigDecimal(0.3); // 2 入參是 String BigDecimal b = new BigDecimal("0.3"); // 3 靜態(tài)方法, 入參是 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
這就很好的解決了上面場景中出現的問題
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 進行除法計算時, 強烈建議使用指定保留小數倍數和舍入模式這個方法, 這樣可以避免除不盡造成的異常.
/** * 參數1: 除數 * 參數2: 保留小數的位數 * 參數3: 舍入模式 */ public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
5. 保留小數和舍入模式
設置保留小數和舍入模式 setScale 方法
BigDecimal price = new BigDecimal("9.936"); price = price.setScale(2, RoundingMode.HALF_UP); // 2位, 四舍五入 System.out.println(price); // 9.94
6. BigDecimal 轉化為 double
double value = c4.doubleValue();
總結
使用 BigDecimal 計算時要注意以下幾點:
- 不建議使用入參是 double 的構造器, 因為它仍然存在精度問題.
- 強烈建議使用入參是 string 的構造器, 或者使用靜態(tài)方法 valueOf 創(chuàng)建對象, 才能保證精度.
- 使用 BigDecimal 做 除法 時, 必須要使用 divide(BigDecimal divisor, int scale, RoundingMode roundingMode), 防止除不盡造成異常.
到此這篇關于Java BigDecimal解決double精度丟失的問題的文章就介紹到這了,更多相關Java BigDecimal double精度丟失內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?Boot項目集成Knife4j接口文檔的實例代碼
Knife4j就相當于是swagger的升級版,對于我來說,它比swagger要好用得多<BR>,這篇文章主要介紹了Spring?Boot項目集成Knife4j接口文檔的示例代碼,需要的朋友可以參考下2021-12-12解決nacos升級spring cloud 2020.0無法使用bootstrap.yml的問題
這篇文章主要介紹了解決nacos升級spring cloud 2020.0無法使用bootstrap.yml的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06