專案需求需將貨幣數字轉為中文大寫(如 10020002.23 → 壹仟零貳萬零貳元貳角三分)。網路常見做法多用 Replace 字串取代,本文採用純數學遞迴演算法,支援 10²³ 以內(9999 億兆)金額,精確至分。
10020002.23 → 壹仟零貳萬零貳元貳角三分1020 → 壹仟零貳拾元整100000 → 拾萬元整0.13 → 壹角三分NumCast 設計public enum NumLevel { Cent, Chiao, Yuan, Ten, Hundred, Thousand, TenThousand, HundredMillion, Trillion }
private int[] NumLevelExponent = { -2, -1, 0, 1, 2, 3, 4, 8, 12 }; // 10 的指數
private string[] NumLevelChinese = { "分", "角", "元", "拾", "佰", "仟", "萬", "億", "兆" };
private string[] NumChineseChar = { "零", "壹", "貳", "三", "肆", "伍", "陸", "柒", "捌", "玖" };
private const string EndOfInt = "整";
public bool IsValidated<T>(T num)
{
var reg = new Regex(@"^(([0])|([1-9]\d{0,23}))(\.\d{1,2})?$");
return reg.IsMatch(num.ToString());
}
GetNumLevel利用 Math.Log10 計算數量級,對應 NumLevel 列舉。
IsJumpLevel比較當前位級與餘數最高位級,差距 > 1 表示需補零(如 302 → 三百零二)。
SplitNum將超出 double 精確範圍的數字字串,以「兆」為界分為高低兩段 double[],分別轉換再合併。
IsStartWithTen中文習慣「壹拾」簡寫為「拾」,需偵測並處理。
CalculateChineseSignprefixNum(最高位數字)與 postfixNum(餘數)。IsJumpLevel 決定是否插入「零」。ConvertToChinesepublic string ConvertToChinese(string numStr)
{
if (!IsValidated(numStr))
throw new OverflowException("格式錯誤或超過 9999 億兆");
if (IsBigThanTrillion(numStr))
{
var parts = SplitNum(numStr);
return CombineTrillionParts(parts);
}
else
{
double val = Convert.ToDouble(numStr);
return CalculateChineseSign(val, null, true, IsStartWithTen(val));
}
}
static void Main()
{
var nc = new NumCast();
Console.WriteLine(nc.ConvertToChinese("10020002.23")); // 壹仟零貳萬零貳元貳角三分
Console.WriteLine(nc.ConvertToChinese("1020")); // 壹仟零貳拾元整
Console.WriteLine(nc.ConvertToChinese("0.13")); // 壹角三分
}
將需求抽象為數學模型(位級指數、遞迴分解、跨位判斷),比字串取代法更具擴充性與邏輯嚴謹性。演算法靈魂在於數學建模,能有效降低程式複雜度並提升穩定性。