惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
C
Check Point Blog
博客园_首页
B
Blog
D
Docker
U
Unit 42
量子位
I
InfoQ
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
GbyAI
GbyAI
L
LangChain Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
美团技术团队
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
Vercel News
Vercel News
Recent Announcements
Recent Announcements
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Google DeepMind News
Google DeepMind News

博客园 - imzhi

VS Code 1.86.1 Requires glibc 2.28 or Later vscode 多个光标自动生成从0开始的数字 js 处理 19.9*0.95 浮点数精度问题的正确姿势,不引入第三方库 ssh 无法用密钥登录 send_pubkey_test: no mutual signature algorithm iqoo手机关掉视频彩铃 pc.vivo.com vivo办公套件网页,拼图验证失败的原因 公司自有服务器无法请求在指向自己服务器的其他域名的API 【转】Cialdini Quiz Explained 机械革命code01 v2.0 开机黑屏,电源键是亮着的 html table表格导入excel文件的方法 微信支付api 付款到银行卡v2 商家转账v3 openssl3.0 php 使用 openssl_encrypt des-ecb 加密报错 error:0308010C:digital envelope routines::unsupported php pdo 写入 sqlserver image类型字段的写法 连接位置国外的远程桌面,使用anydesk thinkphp console 命令行打印错误调用堆栈 【gpt搬运】bash脚本压缩png,jpg图片,当图片大小大于60kb或者尺寸大于500px*500px的时候 【gpt搬运】bash脚本压缩png,jpg图片,当图片大小大于100kb的时候 win10系统休眠、睡眠、关机后进入假死状态的解决方案 如何返回“无法访问此网站,网页可能暂时无法连接,或者它已经永久性地移动到了新网址” dbeaver 升级 24.1.x 版本提示 An error has occurred 的解决
php实现数字转中文大写金额表示
imzhi · 2025-06-24 · via 博客园 - imzhi

通义里给出的回答,但在实践中发现问题,只要第1个数字是6,那转换出来结果就是乱码。

<?php

function numberToChinese($num) {
    // 判断是否是数字
    if (!is_numeric($num)) {
        return '请输入数字';
    }

    // 数字转字符串并处理小数点
    $num = sprintf('%.2f', $num);  // 保留两位小数
    list($integer, $decimal) = explode('.', $num);

    // 定义映射关系
    $digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
    $units = ['', '拾', '佰', '仟'];
    $bigUnits = ['', '万', '亿', '万亿'];

    // 处理整数部分
    $integerStr = '';
    $length = strlen($integer);
    $zeroFlag = false;

    for ($i = 0; $i < $length; $i++) {
        $pos = $length - $i - 1;
        $digit = (int)$integer[$i];
        $unit = $pos % 4;
        $bigUnit = floor($pos / 4);

        if ($digit === 0) {
            if (!$zeroFlag && ($integerStr !== '')) {
                $integerStr .= $digits[0];
                $zeroFlag = true;
            }
        } else {
            $zeroFlag = false;
            $integerStr .= $digits[$digit] . $units[$unit];

            // 添加“万”、“亿”等单位
            if ($unit === 0 && $bigUnits[$bigUnit] !== '') {
                $integerStr .= $bigUnits[$bigUnit];
            }
        }
    }

    // 去除多余的零
    $integerStr = str_replace($digits[0] . $digits[0], $digits[0], $integerStr);
    $integerStr = trim($integerStr, $digits[0]);

    // 处理小数部分
    $decimalStr = '';
    if ((int)$decimal > 0) {
        $jiao = (int)substr($decimal, 0, 1);
        $fen = (int)substr($decimal, 1, 1);
        if ($jiao > 0) {
            $decimalStr .= $digits[$jiao] . '角';
        }
        if ($fen > 0) {
            $decimalStr .= $digits[$fen] . '分';
        }
    } else {
        $decimalStr = '整';
    }

    // 拼接结果
    return $integerStr . '元' . $decimalStr;
}

// 示例用法
$amount = 12345.67;
echo numberToChinese($amount);  // 输出:壹万贰仟叁佰肆拾伍元陆角柒分

问题代码在于第47行的$integerStr = trim($integerStr, $digits[0]);
如果 $integerStr : 陆,$digits[0]:零零。返回的结果就是乱码。

修复代码:

$integerStr = preg_replace("/{$digits[0]}+$/", '', $integerStr);
$integerStr = preg_replace("/^{$digits[0]}+/", '', $integerStr);

最终完整代码

/**
 * @param float $num
 * @return string
 */
public function numberToChinese($num) {
    // 判断是否是数字
    if (!is_numeric($num)) {
        return '请输入数字';
    }

    // 数字转字符串并处理小数点
    $num = sprintf('%.2f', $num);  // 保留两位小数
    list($integer, $decimal) = explode('.', $num);

    // 定义映射关系
    $digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
    $units = ['', '拾', '佰', '仟'];
    $bigUnits = ['', '万', '亿', '万亿'];

    // 处理整数部分
    $integerStr = '';
    $length = strlen($integer);
    $zeroFlag = false;

    for ($i = 0; $i < $length; $i++) {
        $pos = $length - $i - 1;
        $digit = (int)$integer[$i];
        $unit = $pos % 4;
        $bigUnit = floor($pos / 4);

        if ($digit === 0) {
            if (!$zeroFlag && ($integerStr !== '')) {
                $integerStr .= $digits[0];
                $zeroFlag = true;
            }
        } else {
            $zeroFlag = false;
            $integerStr .= $digits[$digit] . $units[$unit];

            // 添加“万”、“亿”等单位
            if ($unit === 0 && $bigUnits[$bigUnit] !== '') {
                $integerStr .= $bigUnits[$bigUnit];
            }
        }
    }

    // 去除多余的零
    $integerStr = str_replace($digits[0] . $digits[0], $digits[0], $integerStr);
    // $integerStr:陆 $digits[0]:零零
    // $integerStr = trim($integerStr, $digits[0]);
    $integerStr = preg_replace("/{$digits[0]}+$/", '', $integerStr);
    $integerStr = preg_replace("/^{$digits[0]}+/", '', $integerStr);

    // 处理小数部分
    $decimalStr = '';
    if ((int)$decimal > 0) {
        $jiao = (int)substr($decimal, 0, 1);
        $fen = (int)substr($decimal, 1, 1);
        if ($jiao > 0) {
            $decimalStr .= $digits[$jiao] . '角';
        }
        if ($fen > 0) {
            $decimalStr .= $digits[$fen] . '分';
        }
    } else {
        $decimalStr = '整';
    }

    // 拼接结果
    return $integerStr . '元' . $decimalStr;
}