本文目录导读:

我来为你提供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";
}
使用注意事项
- 精度问题:对于浮点数,建议使用
number_format()或round()处理精度 - 大数处理:支持万亿级别的数字
- 特殊情况:
- 数字 10 显示为"十"而非"一十"
- 连续的零合并为一个"零"
- 金额为零时显示为"零元整"
这些代码涵盖了常见的数字转中文需求,可以根据具体场景选择使用。