財務系統、支付模塊、報表打印常需將阿拉伯數字轉為中文大寫金額 (「壹貳參肆伍陸柒捌玖拾佰仟萬億」)。本文提供一個健壯、高效、支持長整型範圍 (萬億級) 的 C++ 實現,核心邏輯為「四位分級、逐級轉換、零值智能處理」。
// 位權單位:個十百千 (級內)
static const char* s_unit1[] = { "拾", "佰", "仟" };
// 級單位:萬、億 (中文按 4 位分級)
static const char* s_unit2[] = { "萬", "億" };
// 數字映射
static const char* s_digital[] = { "零", "壹", "貳", "參", "肆", "伍", "陸", "柒", "捌", "玖" };
中文數字讀法按 4 位一級 (個/萬/億) 分組。將長整型拆解為三級:
level1:個級 (佰位以下)level2:萬級level3:億級超過 9999 億 (即萬億) 超出處理範圍,返回失敗。
將 0~9999 數值轉為逆序字符串 (便於後續拼接),智能處理「零」的輸出規則:
static void GetLevelText(long level, char* buf) {
int digit;
bool bPreZero = false; // 上一位是否為零
bool bZeroValidate = false; // 是否已輸出過非零數字 (決定是否輸出前導零)
int i = 0; // buf 寫入位置 (按雙字節字符計算)
int unit = -1; // 單位索引
while (level > 0) {
digit = level % 10;
if (digit != 0) {
// 處理前導零:如果前一位是零且已有非零輸出,補一個「零」
if (bPreZero && bZeroValidate) {
strcat(buf, s_digital[0]); i += 2;
}
// 輸出位權單位 (拾/佰/千)
if (unit != -1) {
strcat(buf, s_unit1[unit]); i += 2;
}
// 輸出數字
strcat(buf, s_digital[digit]); i += 2;
bPreZero = false;
bZeroValidate = true;
} else {
bPreZero = true; // 標記遇到零
}
unit++;
level /= 10;
}
buf[i] = '\0'; // 結束符
}
BOOL Num2UpDigit(long num, char* buf) {
long level1, level2, level3;
char level1buf[17] = {0}, level2buf[17] = {0}, level3buf[17] = {0};
int p = 0; // buf 寫入指針
// 1. 拆分三級 (從低位向高位)
level1 = num % 10000; num /= 10000;
level2 = num % 10000; num /= 10000;
level3 = num;
if (num / 10000) return FALSE; // 超過 9999 億
// 2. 逐級轉換 (逆序字符串)
if (level1) GetLevelText(level1, level1buf);
if (level2) GetLevelText(level2, level2buf);
if (level3) GetLevelText(level3, level3buf);
// 3. 逆序拼接並插入級單位 (萬/億)
// 處理億級
if (level3) {
for (int i = strlen(level3buf) - 2; i >= 0; i -= 2) {
memcpy(buf + p, level3buf + i, 2); p += 2;
}
memcpy(buf + p, s_unit2[1], 2); p += 2; // "億"
}
// 處理萬級
if (level2) {
// 跨級補零:億級存在且萬級千位為 0 (如 1億0001萬)
if (level3 && (level2 / 1000 == 0)) {
memcpy(buf + p, s_digital[0], 2); p += 2;
}
for (int i = strlen(level2buf) - 2; i >= 0; i -= 2) {
memcpy(buf + p, level2buf + i, 2); p += 2;
}
memcpy(buf + p, s_unit2[0], 2); p += 2; // "萬"
} else if (level3 && level1) { // 億級存在、萬級為 0、個級非 0 → 補「零」
memcpy(buf + p, s_digital[0], 2); p += 2;
}
// 處理個級
if (level1) {
// 跨級補零:高級存在且個級千位為 0,且非 (億級存在且萬級為 0) 的特殊情況
if ((level2 || level3) && (level1 / 1000 == 0) && !(level3 && !level2)) {
memcpy(buf + p, s_digital[0], 2); p += 2;
}
for (int i = strlen(level1buf) - 2; i >= 0; i -= 2) {
memcpy(buf + p, level1buf + i, 2); p += 2;
}
}
buf[p] = '\0';
return TRUE;
}
| 輸入數值 | 輸出字符串 | 說明 |
|---|---|---|
| 0 | (空串/需特判) | 建議調用前特判 0 返回「零元整」 |
| 5 | 伍 | 個位 |
| 10 | 壹拾 | 十位 |
| 101 | 壹佰零壹 | 中間零 |
| 1001 | 壹仟零壹 | 連續零只出一個 |
| 10000 | 壹萬 | 級單位 |
| 10001 | 壹萬零壹 | 跨級補零 |
| 100000001 | 壹億零壹 | 萬級為零補零 |
| 123456789 | 壹億貳仟叁佰肆拾伍萬陸仟柒佰捌拾玖 | 完整三級 |
int64_t 或 long long 支持 64 位整數 (9223 萬億),修改分級邏輯為 4 級 (個/萬/億/兆)。double 拆分整數/小數部分分別轉換,拼接「元/角/分/整」。wchar_t/std::wstring 避免多字節字符 memcpy 截斷風險。「四位分級、逆序生成、智能補零」是中文大寫轉換的經典算法模式。本實現代碼緊湊、無外部依賴、易於移植至嵌入式、驅動層或跨平台庫。結合現代 C++ (std::string, string_view, constexpr) 可進一步提升類型安全與性能。