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

Java 實現阿拉伯數字金額轉中文大寫(財務級)

     編輯:Java 相關知識

需求背景

財務系統、票據打印、合同生成等場景常需將數字金額(如 1234.56)轉為中文大寫格式(壹仟貳佰叁拾肆元伍角陸分)。標準大寫字符:

數字:零 壹 貳 叁 肆 伍 陸 柒 捌 玖
單位:分 角 元 拾 佰 仟 萬 拾萬 佰萬 仟萬 億 ...

核心算法實現

import java.math.BigDecimal;
import java.math.RoundingMode;

public class ChineseAmountConverter {
    
    private static final String[] DIGITS = {"零", "壹", "貳", "叁", "肆", "伍", "陸", "柒", "捌", "玖"};
    private static final String[] UNITS = {"", "拾", "佰", "仟"};
    private static final String[] BIG_UNITS = {"", "萬", "億", "兆"}; // 擴展單位
    
    private static final String YUAN = "元";
    private static final String ZHENG = "整";

    /**
     * 轉換入口:支持長整型、BigDecimal、字符串
     */
    public static String convert(Object amount) {
        if (amount == null) return "零元整";
        
        BigDecimal bd;
        if (amount instanceof BigDecimal) {
            bd = (BigDecimal) amount;
        } else if (amount instanceof Number) {
            bd = new BigDecimal(amount.toString());
        } else {
            bd = new BigDecimal(amount.toString().trim());
        }
        
        // 保留兩位小數,四捨五入
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        
        // 分離整數部分和小數部分
        long yuanPart = bd.longValue();           // 元部分
        int fenPart = bd.remainder(BigDecimal.ONE) // 小數部分
                            .movePointRight(2)
                            .intValue();            // 轉為分(角*10 + 分)
        
        String yuanStr = convertIntegerPart(yuanPart);
        String fenStr = convertDecimalPart(fenPart);
        
        return yuanStr + fenStr;
    }

    /** 處理整數部分(元) */
    private static String convertIntegerPart(long num) {
        if (num == 0) return "零" + YUAN;
        
        StringBuilder sb = new StringBuilder();
        int unitIndex = 0; // 萬/億單位索引
        
        while (num > 0) {
            int section = (int) (num % 10000); // 取低4位
            if (section != 0) {
                String sectionStr = convertSection(section);
                sb.insert(0, sectionStr + BIG_UNITS[unitIndex]);
            } else if (sb.length() > 0 && !sb.toString().startsWith("零")) {
                // 中間有0段,補零
                sb.insert(0, DIGITS[0]);
            }
            num /= 10000;
            unitIndex++;
        }
        
        return sb.append(YUAN).toString();
    }

    /** 處理4位一段(千/百/十/個) */
    private static String convertSection(int num) {
        StringBuilder sb = new StringBuilder();
        boolean zeroFlag = false;
        
        for (int i = 0; i < 4; i++) {
            int digit = num % 10;
            if (digit == 0) {
                zeroFlag = true;
            } else {
                if (zeroFlag) {
                    sb.insert(0, DIGITS[0]);
                    zeroFlag = false;
                }
                sb.insert(0, DIGITS[digit] + UNITS[i]);
            }
            num /= 10;
        }
        
        // 處理段內尾部零(如 1000 -> 壹仟,不需補零)
        return sb.toString().replaceAll("零+$", "");
    }

    /** 處理小數部分(角分) */
    private static String convertDecimalPart(int fen) {
        if (fen == 0) return ZHENG;
        
        int jiao = fen / 10;
        int fenDigit = fen % 10;
        StringBuilder sb = new StringBuilder();
        
        if (jiao > 0) sb.append(DIGITS[jiao]).append("角");
        if (fenDigit > 0) sb.append(DIGITS[fenDigit]).append("分");
        if (jiao == 0 && fenDigit > 0) sb.insert(0, DIGITS[0]); // 0角X分 -> 零角X分
        
        return sb.toString();
    }
}

測試用例驗證

public static void main(String[] args) {
    // 基礎測試
    System.out.println(convert(0));                    // 零元整
    System.out.println(convert(1011));                 // 壹仟零壹拾壹元整
    System.out.println(convert("1234.56"));            // 壹仟貳佰叁拾肆元伍角陸分
    System.out.println(convert("10000"));              // 壹萬元整
    System.out.println(convert("100000000"));          // 壹億元整
    System.out.println(convert("100000001"));          // 壹億零壹元整
    System.out.println(convert("1000.01"));            // 壹仟元零壹分
    System.out.println(convert("0.01"));               // 零元零壹分
    System.out.println(convert("123456789.99"));       // 壹億貳仟叁佰肆拾伍萬陸仟柒佰捌拾玖元玖角玖分
    
    // BigDecimal 精度測試
    System.out.println(convert(new BigDecimal("0.005"))); // 零元零壹分 (四捨五入)
}

關鍵設計要點

  1. BigDecimal 避免浮點誤差:金額計算絕不使用 double/float
  2. 四段式處理:按「萬/億」分段,段內按「千/百/十/個」處理
  3. 零的智能處理:連續零合併、段間零補充、尾部零去除
  4. 擴展性:BIG_UNITS 可輕鬆擴展到「兆/京」等更大單位
  5. 邊界情況:0值、純小數、大數字、小數四捨五入全覆蓋

生產環境建議

  • 添加輸入校驗:負數處理、超大數值截斷、非數字字符過濾
  • 考慮國際化:預留貨幣符號參數(¥/$/€)
  • 單元測試覆蓋:邊界值、異常輸入、性能基準
  • 若需高頻調用,可緩存 BigDecimal 實例或預編譯正則
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved