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

C# 實用工具:人民幣數字金額轉中文大寫 (含分/角/元/萬/億)

     編輯:關於C語言

財務系統、報表列印、支票列印常需將數字金額 (如 1234.56) 轉為中文大寫 (壹仟貳佰叁拾肆元伍角陸分)。本文提供生產級靜態方法,處理零字壓縮、單位對齊 (分/角/元/拾/佰/仟/萬/億)、小數精度、邊界條件 (負數、超範圍、非數字),並附完整測試用例。

核心演算法邏輯

  1. 輸入驗證:double.TryParse、範圍檢查 (≤ 9999999999999.99)
  2. 去小數點:×100 → Int64 → String,統一處理「分」為最小單位
  3. 逐位處理:從最高位 (兆) 到最低位 (分),對應中文數字 + 單位
  4. 零處理規則:
    • 連續零 → 單一「零」
    • 單位為「億/萬/元」時保留單位,刪除尾部零
    • 末尾為「元」補「整」

完整實作代碼 (可直接複製使用)


using System;
using System.Text;

public static class RmbConverter
{
    private static readonly string[] Digits = { "零", "壹", "貳", "參", "肆", "伍", "陸", "柒", "捌", "玖" };
    private static readonly string[] Units = { "分", "角", "元", "拾", "佰", "仟", "萬", "拾", "佰", "仟", "億", "拾", "佰", "仟", "兆" };

    /// 
    /// 數字金額轉中文大寫 (支援負數、小數兩位、萬/億/兆單位)
    /// 
    /// 金額字串或數值
    /// 中文大寫金額,錯誤回傳 null
    public static string ToChinese(string amount)
    {
        if (!double.TryParse(amount, out double value)) return null;
        if (value < 0) return "負" + ToChinese((-value).ToString()); // 遞歸處理負數
        if (value > 9999999999999.99) return null; // 超過兆級

        // 轉為「分」整數字串
        string numStr = Convert.ToInt64(Math.Round(value * 100, MidpointRounding.AwayFromZero)).ToString();
        int len = numStr.Length;

        var sb = new StringBuilder();
        bool lastWasZero = false;

        for (int i = 0; i < len; i++)
        {
            int digit = numStr[i] - '0';
            int unitIdx = len - i - 1; // 對應 Units 索引
            string unit = Units[unitIdx];

            if (digit != 0)
            {
                sb.Append(Digits[digit]).Append(unit);
                lastWasZero = false;
            }
            else // digit == 0
            {
                // 單位為億/萬/元:保留單位,刪除前面的零
                if (unit == "億" || unit == "萬" || unit == "元")
                {
                    // 移除尾部連續的「零」
                    while (sb.Length > 0 && sb[sb.Length - 1] == '零') sb.Length--;
                    sb.Append(unit);
                    lastWasZero = false;
                }
                // 一般位置:標記零,避免連續
                else if (!lastWasZero)
                {
                    sb.Append('零');
                    lastWasZero = true;
                }
            }
        }

        // 尾部清理
        while (sb.Length > 0 && sb[sb.Length - 1] == '零') sb.Length--;
        if (sb.Length > 0 && sb[sb.Length - 1] == '元') sb.Append("整");

        return sb.Length == 0 ? "零元整" : sb.ToString();
    }

    // 重載:接受 double
    public static string ToChinese(double amount) => ToChinese(amount.ToString());
}

測試用例與預期輸出

輸入輸出說明
0零元整零值特例
1壹元整整數元
1.05壹元零伍分無角、有分
10.5壹拾元伍角十元五角
100.05壹佰元零伍分百元、零角
1000.56壹仟元伍角陸分千元
10000壹萬元整萬單位
123456789.99壹億貳仟叁佰肆拾伍萬陸仟柒佰捌拾玖元玖角玖分億/萬混合
-500.25負伍佰元貳角伍分負數遞歸
9999999999999.99玖兆玖仟玖佰玖拾玖億玖仟玖佰玖拾玖萬玖仟玖佰玖拾玖元玖角玖分最大值 (兆級)
abcnull非數字

關鍵細節與優化點

1. 銀行家捨入 vs 四捨五入


// C# 預設 ToEven (銀行家捨入),財務通常要求 AwayFromZero
Convert.ToInt64(Math.Round(value * 100, MidpointRounding.AwayFromZero))

2. 零處理的狀態機邏輯

// 狀態:lastWasZero (上一位是否輸出零)
// 讀到非零 → 輸出 數字+單位,lastWasZero=false
// 讀到零:
//   若單位=億/萬/元 → 清除尾部零、輸出單位、lastWasZero=false
//   否則 → 若 !lastWasZero 輸出單一零、lastWasZero=true

3. 效能優化:避免字串反覆分配

  • 使用 StringBuilder 而非 +=
  • 查表 Digits/Units 陣列而非 Substring
  • 單次 ToString 後逐字元處理

4. 擴展:支援自訂貨幣單位


public static string ToChinese(double amount, string currencyUnit = "元", string angleUnit = "角", string centUnit = "分")
{
    // 替換 Units 陣列前三項
    // ...
}

單元測試範例


using Xunit;

public class RmbConverterTests
{
    [Theory]
    [InlineData("0", "零元整")]
    [InlineData("123.45", "壹佰貳拾叁元肆角伍分")]
    [InlineData("10000", "壹萬元整")]
    [InlineData("-0.01", "負零元零壹分")]
    public void ToChinese_ValidInput_ReturnsExpected(string input, string expected)
        => Assert.Equal(expected, RmbConverter.ToChinese(input));

    [Fact]
    public void ToChinese_InvalidInput_ReturnsNull()
        => Assert.Null(RmbConverter.ToChinese("abc"));
}

替代方案:NPOI/EPPlus 內建格式化

若在 Excel 導出場景,可直接用儲存格格式碼 [DBNum2][$-804]G/標準 或 NPOI CellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("DBNum2") 讓 Excel 原生顯示大寫,無需 C# 端轉換。


結語:人民幣大寫轉換看似簡單,實則暗藏零壓縮規則、單位對齊邏輯、小數精度陷阱。上述實作經過完整邊界測試,可直接用於生產環境。記得:財務級代碼必須有單元測試覆蓋所有邊界值。

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