首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 大數運算實戰:BigDecimal 精確加法與最佳實踐指南

     編輯:Java 相關知識

為什麼需要 BigDecimal

float/double 基於 IEEE 754 浮點數表示,無法精確表達許多十進制小數(如 0.1),導致財務、科學計算出現誤差:

System.out.println(0.1 + 0.2); // 0.30000000000000004
System.out.println(1.0 - 0.9); // 0.09999999999999998

BigDecimal 提供任意精度的有理數運算,是金融、計量等精度敏感領域的標準選擇。

精確加法完整示例

import java.math.BigDecimal;
import java.util.Scanner;

public class BigDecimalAddition {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("請輸入第一個大數: ");
        String num1 = scanner.next();
        System.out.print("請輸入第二個大數: ");
        String num2 = scanner.next();
        
        // 推薦使用 String 構造器,避免 double 精度損失
        BigDecimal bd1 = new BigDecimal(num1);
        BigDecimal bd2 = new BigDecimal(num2);
        
        BigDecimal sum = bd1.add(bd2);
        System.out.println("精確相加結果: " + sum);
        
        scanner.close();
    }
}

核心 API 快速參考

操作方法說明
加法add(BigDecimal)返回新 BigDecimal,原對象不可變
減法subtract(BigDecimal)
乘法multiply(BigDecimal)
除法divide(BigDecimal, scale, RoundingMode)必須指定精度與舍入模式,否則可能拋 ArithmeticException
比較compareTo(BigDecimal)返回 -1/0/1,勿用 equals(比較 scale)
格式化setScale(scale, RoundingMode)設置小數位數與舍入規則

除法精度控制示例

BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");

// 保留 2 位小數,四捨五入
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); 
// 結果: 3.33

// 不指定精度會拋異常:Non-terminating decimal expansion
// BigDecimal wrong = a.divide(b); // ❌

構造器選擇陷阱

// ❌ 錯誤:double 精度損失已在構造前發生
new BigDecimal(0.1); // 0.1000000000000000055511151231257827021181583404541015625

// ✅ 正確:String 構造器精確表達
new BigDecimal("0.1"); // 0.1

// ✅ 正確:valueOf 內部用 Double.toString 轉換
BigDecimal.valueOf(0.1); // 0.1

性能與優化建議

  • 不可變模式:每次運算創建新對象,高頻計算可復用對象或考慮 long 整數分/厘存儲
  • 上下文控制:MathContext 統一精度與舍入模式
  • 數據庫映射:JPA 使用 @Column(precision=19, scale=4) 對應 BigDecimal
  • JSON 序列化:Jackson 默認輸出數值,大數建議配置 JsonSerialize(using = ToStringSerializer.class) 避免科學計數法
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved