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

PHP 金額數字轉中文大寫:四種實現方案完整代碼

     編輯:PHP 相關知識

PHP 金額數字轉中文大寫:四種實現方案完整代碼

財務系統、支票打印、合同生成常需將阿拉伯數字轉為「壹佰貳拾叁元整」格式。本文收錄四種風格迥異的實現:陣列映射、逐位遞歸、正則修補、JS 移植版,供不同場景選擇。

方案一:陣列映射 + 單位陣列(推薦,簡潔高效)

function toChineseNumber(float $money): string {
    $money = round($money, 2);
    $nums  = ["零","壹","貳","三","肆","伍","陸","柒","捌","玖"];
    $units = ["圓","角","分"];
    $grades= ["拾","佰","仟","萬","拾","佰","仟","億"];

    [$int, $dec] = explode('.', $money, 2);
    $dec = array_filter([$dec[1]??'', $dec[0]??'']); // 分、角

    $ret = array_merge($dec, [implode('', cnyMapUnit(str_split($int), $grades)), '']);
    $ret = implode('', array_reverse(cnyMapUnit($ret, $units)));
    return str_replace(array_keys($nums), $nums, $ret);
}

function cnyMapUnit(array $list, array $units): array {
    $ul = count($units);
    $xs = [];
    foreach (array_reverse($list) as $x) {
        $l = count($xs);
        if ($x != "0" || !($l % 4)) {
            $n = ($x=='0'?'':$x) . $units[($l-1)%$ul];
        } else {
            $n = is_numeric($xs[0][0]??'') ? $x : '';
        }
        array_unshift($xs, $n);
    }
    return $xs;
}

echo toChineseNumber(1234567890); // 壹拾貳億三仟肆佰伍拾陸萬柒仟捌佰玖拾圓

方案二:逐位處理 + 字符串修補(邏輯清晰,易維護)

function num_to_rmb($num): string {
    $c1 = "零壹貳三肆伍陸柒捌玖";
    $c2 = "分角元拾佰仟萬拾佰仟億";

    $num = round($num, 2) * 100; // 轉分為整數
    if (strlen($num) > 10) return "金額太大";

    $i = 0; $c = "";
    while (true) {
        $n = $i==0 ? substr($num, -1) : $num % 10;
        $p1 = substr($c1, 3*$n, 3);
        $p2 = substr($c2, 3*$i, 3);
        if ($n != '0' || in_array($p2, ['億','萬','元'])) {
            $c = $p1 . $p2 . $c;
        } else {
            $c = $p1 . $c;
        }
        $i++; $num = (int)($num/10);
        if ($num == 0) break;
    }

    // 合併連續「零」、尾部「零」處理
    $j = 0; $slen = strlen($c);
    while ($j < $slen) {
        $m = substr($c, $j, 6); // UTF-8 一漢字 3 字節
        if (in_array($m, ['零元','零萬','零億','零零'])) {
            $c = substr($c,0,$j) . substr($c,$j+3);
            $j -= 3; $slen -= 3;
        }
        $j += 3;
    }
    if (substr($c, -3) == '零') $c = substr($c, 0, -3);
    return $c ? $c . "整" : "零元整";
}

echo num_to_rmb(23000000.00); // 貳仟三佰萬元整

方案三:分段處理(萬/億分段)+ 正則清理(擴展性強)

function convert_2_cn($num) {
    $cn = ["零","壹","貳","三","肆","伍","陸","柒","捌","玖"];
    $repair = ['零仟零佰零拾零','萬萬','零仟','零佰','零拾'];
    $unit = ["拾","佰","仟","萬","億"];
    $exp  = ["","萬","億"];

    $num = str_pad($num, 12, '-', STR_PAD_LEFT);
    $segments = [];
    for ($i=12, $k=0; $i>0; $i--) {
        if ($i%4==0) $k++;
        $segments[$k][] = substr($num, $i-1, 1);
    }

    $str = '';
    foreach ($segments as $k=>$seg) {
        if (array_sum($seg)) $str = array_shift($exp) . $str;
        foreach ($seg as $nk=>$nv) {
            if ($nv=='-') continue;
            $str = ($nk==0 ? $cn[$nv] : $cn[$nv].$unit[$nk-1]) . $str;
        }
    }
    $str = str_replace($repair, ['萬','億','-'], $str);
    $str = preg_replace("/-{2,}/", "", $str);
    return str_replace(['零','-'], ['','零'], $str);
}

// 附贈:中文大寫轉數字
function cn_2_num($str) {
    $cn = ["零","壹","貳","三","肆","伍","陸","柒","捌","玖"];
    $skip = ["拾","佰","仟"];
    $str = str_replace($skip, "", $str);
    $len = mb_strlen($str, 'utf-8');
    $num = 0; $k = '';
    for ($i=0; $i<$len; $i++) {
        $ch = mb_substr($str, $i, 1, 'utf-8');
        if ($ch=='億') { $num += intval($k)*100000000; $k=''; }
        elseif ($ch=='萬') { $num += intval($k)*10000; $k=''; }
        else $k .= array_search($ch, $cn);
    }
    return $num + ($k?intval($k):0);
}

方案四:JS 版移植(前後端統一邏輯)

見原文 convertCurrency() + nst_convert(),含前端輸入格式化(千分位、小數位限制)、輸入框聯動演示。

選型建議

  • 後端純 PHP:方案一或二,單元測試覆蓋邊界(0、負數、小數位、萬/億邊界)。
  • 前後端同構:方案四,Node.js 端可直接複用 JS 版。
  • 高併發:預計算常用金額緩存,或用 C 擴展加速。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved