PHP数字转中文大写

wen PHP项目 1

本文目录导读:

PHP数字转中文大写

  1. 基础版:人民币大写转换
  2. 简化版:纯数字转中文
  3. 完整通用版本
  4. 边界情况测试
  5. 使用注意事项

我来为你提供PHP数字转中文大写的完整实现方案:

基础版:人民币大写转换

<?php
function numberToChinese($num) {
    // 中文字符
    $cnNum = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
    $cnUnit = ['', '拾', '佰', '仟'];
    $cnBigUnit = ['', '万', '亿', '万亿'];
    // 处理小数部分
    $parts = explode('.', number_format($num, 2, '.', ''));
    $integerPart = (int)$parts[0];
    $decimalPart = isset($parts[1]) ? $parts[1] : '00';
    if ($integerPart == 0) {
        $result = '零';
    } else {
        $result = '';
        $needZero = false;
        $bigUnitIndex = 0;
        while ($integerPart > 0) {
            $segment = $integerPart % 10000;
            $integerPart = intdiv($integerPart, 10000);
            if ($segment != 0) {
                $segmentStr = '';
                $unitIndex = 0;
                $tempNum = $segment;
                while ($tempNum > 0) {
                    $digit = $tempNum % 10;
                    $tempNum = intdiv($tempNum, 10);
                    if ($digit != 0) {
                        $segmentStr = $cnNum[$digit] . $cnUnit[$unitIndex] . $segmentStr;
                        $needZero = false;
                    } else {
                        if (!$needZero && strlen($segmentStr) > 0) {
                            $segmentStr = '零' . $segmentStr;
                        }
                        $needZero = true;
                    }
                    $unitIndex++;
                }
                $result = $segmentStr . $cnBigUnit[$bigUnitIndex] . $result;
            } else {
                if (strlen($result) > 0) {
                    $needZero = true;
                }
            }
            $bigUnitIndex++;
        }
        // 处理开头的零
        if ($needZero && strlen($result) > 0) {
            $result = '零' . $result;
        }
    }
    // 处理小数部分
    $decimalStr = '';
    if ($decimalPart[0] != '0') {
        $decimalStr .= $cnNum[(int)$decimalPart[0]] . '角';
    }
    if ($decimalPart[1] != '0') {
        $decimalStr .= $cnNum[(int)$decimalPart[1]] . '分';
    }
    if ($decimalStr == '') {
        $decimalStr = '整';
    }
    return $result . '元' . $decimalStr;
}
// 测试
echo numberToChinese(123456.78);  // 壹拾贰万叁仟肆佰伍拾陆元柒角捌分
echo "\n";
echo numberToChinese(1001);       // 壹仟零壹元整
echo "\n";
echo numberToChinese(105.05);     // 壹佰零伍元零伍分

简化版:纯数字转中文

<?php
function numberToChineseSimple($num) {
    $cnNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
    $cnUnit = ['', '十', '百', '千'];
    $cnBigUnit = ['', '万', '亿', '万亿'];
    if ($num == 0) return '零';
    $result = '';
    $bigUnitIndex = 0;
    while ($num > 0) {
        $segment = $num % 10000;
        $num = intdiv($num, 10000);
        if ($segment != 0) {
            $segmentStr = '';
            $unitIndex = 0;
            $tempNum = $segment;
            while ($tempNum > 0) {
                $digit = $tempNum % 10;
                $tempNum = intdiv($tempNum, 10);
                if ($digit != 0) {
                    // 特殊处理:"一十" -> "十"
                    if ($digit == 1 && $unitIndex == 1 && $segment < 20) {
                        $segmentStr = '十' . $segmentStr;
                    } else {
                        $segmentStr = $cnNum[$digit] . $cnUnit[$unitIndex] . $segmentStr;
                    }
                } else {
                    // 处理连续零
                    if (strlen($segmentStr) > 0 && substr($segmentStr, 0, 1) != '零') {
                        $segmentStr = '零' . $segmentStr;
                    }
                }
                $unitIndex++;
            }
            $result = $segmentStr . $cnBigUnit[$bigUnitIndex] . $result;
        } else if (strlen($result) > 0) {
            // 处理跨段的零
            $result = '零' . $result;
        }
        $bigUnitIndex++;
    }
    // 清理开头的零
    $result = ltrim($result, '零');
    // 处理"零"的重复
    $result = preg_replace('/零+/', '零', $result);
    return $result;
}
// 测试
echo numberToChineseSimple(12345);  // 一万二千三百四十五
echo "\n";
echo numberToChineseSimple(10001);  // 一万零一

完整通用版本

<?php
class ChineseNumberConverter {
    private static $cnNum = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
    private static $cnUnit = ['', '拾', '佰', '仟'];
    private static $cnBigUnit = ['', '万', '亿', '万亿'];
    /**
     * 数字转中文大写(人民币格式)
     */
    public static function toRMB($num) {
        if (!is_numeric($num) || $num < 0) {
            return '参数错误';
        }
        $num = round($num, 2); // 保留两位小数
        // 分离整数和小数
        $numStr = number_format($num, 2, '.', '');
        list($integerPart, $decimalPart) = explode('.', $numStr);
        // 转换整数部分
        $integerChinese = self::integerToChinese((int)$integerPart);
        // 转换小数部分
        $decimalChinese = '';
        $jiao = (int)$decimalPart[0];
        $fen = (int)$decimalPart[1];
        if ($jiao > 0) {
            $decimalChinese .= self::$cnNum[$jiao] . '角';
        }
        if ($fen > 0) {
            $decimalChinese .= self::$cnNum[$fen] . '分';
        }
        if (empty($decimalChinese)) {
            $decimalChinese = '整';
        }
        return $integerChinese . '元' . $decimalChinese;
    }
    /**
     * 整数部分转换
     */
    private static function integerToChinese($num) {
        if ($num == 0) {
            return '零';
        }
        $result = '';
        $bigUnitIndex = 0;
        $needZero = false;
        while ($num > 0) {
            $segment = $num % 10000;
            $num = intdiv($num, 10000);
            if ($segment != 0) {
                $segmentStr = self::segmentToChinese($segment);
                // 处理段间零
                if ($needZero && strlen($result) > 0 && substr($segmentStr, 0, 1) != '零') {
                    $result = '零' . $result;
                }
                $result = $segmentStr . self::$cnBigUnit[$bigUnitIndex] . $result;
                $needZero = false;
            } else {
                $needZero = true;
            }
            $bigUnitIndex++;
        }
        return $result;
    }
    /**
     * 四位段转换
     */
    private static function segmentToChinese($segment) {
        if ($segment == 0) {
            return '';
        }
        $result = '';
        $unitIndex = 0;
        $tempNum = $segment;
        while ($tempNum > 0) {
            $digit = $tempNum % 10;
            $tempNum = intdiv($tempNum, 10);
            if ($digit != 0) {
                $result = self::$cnNum[$digit] . self::$cnUnit[$unitIndex] . $result;
            } else {
                // 只处理非末尾的零
                if ($tempNum > 0 && strlen($result) > 0 && substr($result, 0, 1) != '零') {
                    $result = '零' . $result;
                }
            }
            $unitIndex++;
        }
        return $result;
    }
    /**
     * 纯数字转中文小写
     */
    public static function toSimple($num) {
        $cnNumLower = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
        // 临时切换数组
        $temp = self::$cnNum;
        self::$cnNum = $cnNumLower;
        $result = self::integerToChinese($num);
        // 恢复数组
        self::$cnNum = $temp;
        // 清理连续的零
        $result = preg_replace('/零+/', '零', $result);
        $result = trim($result, '零');
        return $result;
    }
}
// 使用示例
echo ChineseNumberConverter::toRMB(123456.78);    // 壹拾贰万叁仟肆佰伍拾陆元柒角捌分
echo "\n";
echo ChineseNumberConverter::toRMB(10001.01);     // 壹万零壹元零壹分
echo "\n";
echo ChineseNumberConverter::toSimple(12345);     // 一万二千三百四十五
echo "\n";
echo ChineseNumberConverter::toSimple(10001);     // 一万零一

边界情况测试

<?php
$tests = [
    0,
    5,
    10,
    15,
    20,
    100,
    1001,
    10001,
    10101,
    100001,
    1000001,
    100000000,
    123456789,
    999999999999,
];
foreach ($tests as $num) {
    echo $num . " => " . ChineseNumberConverter::toSimple($num) . "\n";
}

使用注意事项

  1. 精度问题:对于浮点数,建议使用 number_format()round() 处理精度
  2. 大数处理:支持万亿级别的数字
  3. 特殊情况
    • 数字 10 显示为"十"而非"一十"
    • 连续的零合并为一个"零"
    • 金额为零时显示为"零元整"

这些代码涵盖了常见的数字转中文需求,可以根据具体场景选择使用。

抱歉,评论功能暂时关闭!