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

推荐订阅源

WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
Vercel News
Vercel News
Last Week in AI
Last Week in AI
H
Help Net Security
The Cloudflare Blog
L
LangChain Blog
Microsoft Security Blog
Microsoft Security Blog
B
Blog RSS Feed
云风的 BLOG
云风的 BLOG
I
InfoQ
U
Unit 42
美团技术团队
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
Y
Y Combinator Blog
Hugging Face - Blog
Hugging Face - Blog
A
About on SuperTechFans
宝玉的分享
宝玉的分享
量子位
博客园_首页

博客园 - 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;
}