中文数字的特点
- 每个计数数字都跟着一个权位,权位有:十、百、千、万、亿。
- 以“万”为小节,对应一个节权位,万以下没有节权位(例如”一千“)。
- 每个小节内部以“十百千”为权位独立计数。
- “十百千”不能连续出现,而“万”和“亿”作为节权位时可以和其他权位连用,如:“二十亿”。
中文数字对“零”的使用要满足以下三条规则
- 以10000为小节,小节的结尾即使是0,也不使用零,例如”一万“、”一百万四千“。
- 小节内两个非0数字之间要使用“零”,例如”一百零一“。
- 当小节的“千”位是0时,只要不是首小节,都要补“零”,例如“一万零九百九十九”,”九百万零五十“。
算法设计的一些说明:
- 对“零”的第三个规则,把检测放在循环的最前面并默认为false,可以自然的丢弃最高小节的加零判断。
- 把“十一”开头的“十一”改为“十”
代码示例
<?php
//阿拉伯数字转中文数字
function numberToChinese(int $num)
{
//节权位的位置
$unit_section_pos = 0;
$chn_str = '';
//单个数字转换用的数组
$chn_num_char = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
//节权位转换用的数组
$chn_unit_section = ["", "万", "亿", "万亿", "亿亿"];
//节内权位换算的数组
$chn_unit_char = ["", "十", "百", "千"];
$need_zero = false;
if ($num === 0) {
return $chn_num_char[0];
}
//节内换算的闭包
$section_to_chinese = function ($section) use ($chn_num_char, $chn_unit_char) {
$chn_str = '';
//节内的位置
$unit_pos = 0;
$zero = true;
while ($section > 0) {
$v = $section % 10;
if ($v === 0) {
if (!$zero) {
$zero = true;
$chn_str = $chn_num_char[$v] . $chn_str;
}
} else {
$zero = false;
$str_ins = $chn_num_char[$v];
$str_ins .= $chn_unit_char[$unit_pos];
$chn_str = $str_ins . $chn_str;
}
$unit_pos++;
$section = floor($section / 10);
}
return $chn_str;
};
while ($num > 0) {
$section = $num % 10000;
if ($need_zero) {
$chn_str = $chn_num_char[0] . $chn_str;
}
$str_ins = $section_to_chinese($section);
$str_ins .= ($section !== 0) ? $chn_unit_section[$unit_section_pos] : $chn_unit_section[0];
$chn_str = $str_ins . $chn_str;
$need_zero = ($section < 1000) && ($section > 0);
$num = floor($num / 10000);
$unit_section_pos++;
}
$search = '一十';
$replacement = '十';
//处理含一十开头的(这个可根据需求处理)
if (mb_substr($chn_str, 0, 2) === $search) {
$position = strpos($chn_str, $search);
$chn_str = substr_replace($chn_str, $replacement, $position, strlen($search));
}
return $chn_str;
}
echo numberToChinese(1000001);
参考连接
https://segmentfault.com/a/1190000004881457?utm_source=sf-similar-article