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

Java 大數乘法與浮點數乘法手工實現原理與代碼

     編輯:Java 相關知識

背景動機

Java 基本類型 long 最大 9.22e18,double 53 位有效數字約 15-16 位十進制精度。當涉及超大整數(百位以上)精確運算或金融級定點小數運算時,必須實現手工模擬乘法邏輯。

大整數乘法:豎式乘法數組實現

核心思路

  1. 將字符串數字逆序存入 int[],每元素存一位(0-9)
  2. 雙重迴圈模擬手算豎式乘法:result[i+j] += a[i] * b[j]
  3. 統一處理進位:carry = result[k] / 10; result[k] %= 10
  4. 去除前導零,轉回字符串

關鍵代碼片段

public static String multiplyLargeIntegers(String num1, String num2) {
    int[] a = toDigitArray(num1);  // 低位在前
    int[] b = toDigitArray(num2);
    int[] res = new int[a.length + b.length]; // 最大長度

    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < b.length; j++) {
            res[i + j] += a[i] * b[j];
        }
    }

    // 統一進位
    for (int k = 0; k < res.length; k++) {
        int carry = res[k] / 10;
        res[k] %= 10;
        if (k + 1 < res.length) res[k + 1] += carry;
    }

    // 去除前導零並構建字符串
    StringBuilder sb = new StringBuilder();
    boolean leading = true;
    for (int i = res.length - 1; i >= 0; i--) {
        if (leading && res[i] == 0) continue;
        leading = false;
        sb.append(res[i]);
    }
    return sb.length() == 0 ? "0" : sb.toString();
}

浮點數乘法:定點數擴展法

核心思路

  1. 解析兩數的小數位數 d1、d2
  2. 去除小數點,轉為大整數字符串 i1、i2
  3. 調用大整數乘法得 product
  4. 結果插入小數點,位置為 d1 + d2
  5. 去除尾部多餘零,處理符號

完整實現邏輯

public static String multiplyDecimals(String num1, String num2) {
    // 1. 符號處理
    boolean neg = false;
    if (num1.startsWith("-")) { neg = !neg; num1 = num1.substring(1); }
    if (num2.startsWith("-")) { neg = !neg; num2 = num2.substring(1); }

    // 2. 分離小數位
    int d1 = decimalDigits(num1);
    int d2 = decimalDigits(num2);
    String i1 = removeDecimalPoint(num1);
    String i2 = removeDecimalPoint(num2);

    // 3. 大整數相乘
    String product = multiplyLargeIntegers(i1, i2);

    // 4. 插入小數點
    int totalDec = d1 + d2;
    if (totalDec > 0) {
        if (product.length() <= totalDec) {
            product = "0".repeat(totalDec - product.length() + 1) + product;
        }
        product = product.substring(0, product.length() - totalDec) + "." 
                + product.substring(product.length() - totalDec);
    }

    // 5. 去除尾部零 & 標準化
    product = product.replaceFirst("\\.?0+$", ""); // 移除小數點後多餘零
    if (product.startsWith(".")) product = "0" + product;
    if (product.endsWith(".")) product = product.substring(0, product.length() - 1);

    return neg ? "-" + product : product;
}

驗證測試

public static void main(String[] args) {
    // 大整數測試
    String a = "123456789012345678901234567890";
    String b = "987654321098765432109876543210";
    System.out.println("大整數乘積長度: " + multiplyLargeIntegers(a, b).length()); // 60 位

    // 浮點數測試(對比 Python 高精度)
    String x = "-23424.2300";
    String y = "02345.23400000";
    String javaResult = multiplyDecimals(x, y);
    // Python: -23424.2300 * 02345.23400000 = -54935300.619819999
    System.out.println("Java 手工: " + javaResult); 
    // 預期: -54935300.61982 (尾部零已移除)
}

性能與優化方向

優化點說明複雜度提升
Karatsuba 算法分治遞歸,減少乘法次數O(n^1.585)
FFT/NTT 乘法數論變換/快速傅里葉,極大數(萬位+)O(n log n)
基數優化每元素存 4 位(基數 10000)或 9 位(基數 1e9),減少數組長度常數倍加速
原地運算複用數組,減少 GC 壓力記憶體友好

生產環境建議

  • 優先使用 java.math.BigInteger / BigDecimal:經過嚴格測試、JIT 優化、安全審計
  • 手工實現僅用於教學演示、特殊約束環境(無標準庫)、算法面試
  • 若必須自研,務必補全:除法、開方、模運算、隨機生成、素性測試等完整算術體系

總結

手工實現大數/浮點乘法是理解計算機算術基礎的優秀練習。通過「字符串→數組→豎式乘法→進位→格式化」的流程,可清晰掌握任意精度運算的核心邏輯。實際工程中,請擁抱 BigDecimal,並配合 MathContext 控制精度與捨入模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved