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

Java 實現人民幣數字轉中文大寫金額完整算法

     編輯:Java 相關知識

財務系統中將阿拉伯數字金額轉為中文大寫(如 1234.56 → 壹仟貳佰叁拾肆元伍角陸分)是剛需。本文提供健壯、可擴展的完整實現,覆蓋整數/小數、零處理、萬/億單位、負數校驗等邊界情況。

核心難點與設計思路

  1. 四位一節:中文數字按「萬、億」分節,每節內部為「仟、佰、拾、元」。
  2. 零的語義:節內連續零只讀一個「零」;節末尾零不讀;整數部分為零時輸出「零元」。
  3. 小數單位:角、分、厘(可擴展),小數位不足補零、超出截斷/四捨五入。
  4. 輸入校驗:非數字、超出範圍(超過千億)、小數位過多均應拋出異常或返回錯誤提示。

關鍵數據結構

private static final String[] DIGITS = {"零","壹","貳","叁","肆","伍","陸","柒","捌","玖"};
private static final String[] UNITS  = {"","拾","佰","仟"};        // 節內單位
private static final String[] SECTIONS = {"","萬","億","兆"};      // 節單位
private static final String[] FRACTION_UNITS = {"角","分","厘"};   // 小數單位

完整實現(含詳細註釋)

public class ChineseAmountConverter {

    public static String convert(String amount) {
        if (amount == null || amount.trim().isEmpty()) {
            throw new IllegalArgumentException("金額不能為空");
        }
        String num = amount.trim();
        boolean negative = false;
        if (num.startsWith("-")) {
            negative = true;
            num = num.substring(1);
        }
        // 校驗格式:整數部分最長 16 位(千億級),小數最多 3 位
        if (!num.matches("\\d+(\\.\\d{1,3})?")) {
            throw new IllegalArgumentException("非法金額格式");
        }
        String[] parts = num.split("\\.");
        String integerPart = parts[0].replaceFirst("^0+", ""); // 去前導零
        if (integerPart.isEmpty()) integerPart = "0";
        String fractionPart = parts.length > 1 ? parts[1] : "";

        StringBuilder sb = new StringBuilder();
        if (negative) sb.append("負");

        // 整數部分:從低位向高位,四位一節處理
        if ("0".equals(integerPart)) {
            sb.append("零元");
        } else {
            sb.append(processInteger(integerPart));
            sb.append("元");
        }

        // 小數部分
        if (fractionPart.isEmpty() || fractionPart.matches("0+")) {
            sb.append("整");
        } else {
            sb.append(processFraction(fractionPart));
        }
        return sb.toString();
    }

    private static String processInteger(String num) {
        StringBuilder res = new StringBuilder();
        int len = num.length();
        for (int i = 0; i < len; i += 4) {
            int end = len - i;
            int start = Math.max(0, end - 4);
            String section = num.substring(start, end);
            String sectionStr = processSection(section);
            if (!sectionStr.isEmpty()) {
                res.insert(0, sectionStr + SECTIONS[i / 4]);
            }
        }
        return res.toString();
    }

    private static String processSection(String fourDigits) {
        StringBuilder sb = new StringBuilder();
        boolean lastZero = false;
        for (int i = 0; i < fourDigits.length(); i++) {
            int digit = fourDigits.charAt(i) - '0';
            int unitPos = fourDigits.length() - 1 - i; // 3=仟 2=佰 1=拾 0=元
            if (digit == 0) {
                lastZero = true;
            } else {
                if (lastZero) sb.append(DIGITS[0]);
                sb.append(DIGITS[digit]).append(UNITS[unitPos]);
                lastZero = false;
            }
        }
        return sb.toString();
    }

    private static String processFraction(String frac) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < frac.length() && i < FRACTION_UNITS.length; i++) {
            int digit = frac.charAt(i) - '0';
            if (digit != 0) {
                sb.append(DIGITS[digit]).append(FRACTION_UNITS[i]);
            } else if (i + 1 < frac.length()) { // 中間零保留,末尾零省略
                // 檢查後續是否有非零
                boolean hasNonZero = false;
                for (int j = i + 1; j < frac.length(); j++) {
                    if (frac.charAt(j) != '0') { hasNonZero = true; break; }
                }
                if (hasNonZero) sb.append(DIGITS[0]);
            }
        }
        return sb.toString();
    }
}

測試用例與輸出

輸入輸出
0零元整
100909壹拾萬零玖佰零玖元整
1234567.89壹佰貳拾叁萬肆仟伍佰陸拾柒元捌角玖分
1000.01壹仟元零壹分
-0.05負零元伍分

擴展建議

  • 使用 BigDecimal 避免浮點精度問題,支持超大金額。
  • 增加「圓/整」繁體異體字配置,適配港澳台業務。
  • 集成到 Bean Validation 註解 @ChineseAmount 實現聲明式校驗轉換。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved