├── .gitignore ├── .travis.yml ├── README.md ├── composer.json ├── number2chinese.php └── test.php /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | vendor/ 3 | composer.lock -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | dist: trusty 4 | 5 | php: 6 | - 5.4 7 | - 5.6 8 | - 7.0 9 | - 7.1 10 | - 7.2 11 | - 7.3 12 | - 7.4 13 | 14 | sudo: false 15 | 16 | script: 17 | - php test.php 18 | 19 | notifications: 20 | email: 21 | recipients: 22 | - wilonx@163.com 23 | on_success: never 24 | on_failure: never 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP number2chinese 2 | 3 | 点击校验👉👉👉[![Build Status](https://travis-ci.org/wilon/php-number2chinese.svg?branch=master)](https://travis-ci.org/wilon/php-number2chinese) 4 | 5 | [![Packagist][badge_package]][link-packagist] 6 | [![Packagist Release][badge_release]][link-packagist] 7 | [![Packagist Downloads][badge_downloads]][link-packagist] 8 | 9 | [badge_package]: https://img.shields.io/badge/package-wilon/php--number2chinese-blue.svg?style=flat-square 10 | [badge_release]: https://img.shields.io/packagist/v/wilon/php-number2chinese.svg?style=flat-square 11 | [badge_downloads]: https://img.shields.io/packagist/dt/wilon/php-number2chinese.svg?style=flat-square 12 | [link-packagist]: https://packagist.org/packages/wilon/php-number2chinese 13 | 14 | PHP 数字转为汉字描述,人民币大写方法。 15 | 16 | * 个,十,百,千,万,十万,百万,千万,亿,十亿,百亿,千亿,万亿,十万亿,百万亿,千万亿,兆;此函数亿乘以亿为兆 17 | 18 | * 以「十」开头,如十五,十万,十亿等。两位数以上,在数字中部出现,则用「一十几」,如一百一十,一千零一十,一万零一十等 19 | 20 | * 「二」和「两」的问题。两亿,两万,两千,两百,都可以,但是20只能是二十,200用二百也更好。22,2222,2222是「二十二亿两千二百二十二万两千二百二十二」 21 | 22 | * 关于「零」和「〇」的问题,数字中一律用「零」,只有页码、年代等编号中数的空位才能用「〇」。数位中间无论多少个0,都读成一个「零」。2014是「两千零一十四」,200014是「二十万零一十四」,201400是「二十万零一千四百」 23 | 24 | * 参考:https://jingyan.baidu.com/article/636f38bb3cfc88d6b946104b.html 25 | 26 | * 人民币写法参考:[正确填写票据和结算凭证的基本规定](http://bbs.chinaacc.com/forum-2-35/topic-1181907.html) 27 | 28 | ### 安装 29 | 30 | > *php -v >= 5.4* 31 | 32 | 在 `composer.json` 文件中添加 33 | 34 | ```json 35 | "wilon/php-number2chinese": "~1.0" 36 | ``` 37 | 38 | 或者 39 | 40 | ```sh 41 | composer require wilon/php-number2chinese 42 | ``` 43 | 44 | ### 使用方法 45 | 46 | > #string number2chinese ( mixed $number [, bollen $isRmb] )# 47 | 48 | *将$number转为汉字念法* 49 | 50 | * mixed $number 51 | 52 | 输入数字或字符串。 53 | 当数字过大或过小时,请输入string 54 | 支持负数 55 | 56 | * bollen $isRmb 57 | 58 | 默认为false,当为true时返回人民币大写汉字 59 | 人民币最大单位[仟兆],最小单位[毫] 60 | 61 | ### 代码示例 62 | 63 | ```php 64 | $num1 = 0.1234567890; 65 | echo number2chinese($num1); // 零点一二三四五六七八九 66 | echo number2chinese($num1, true); // 零元壹角贰分叁厘肆毫 67 | $num2 = 20000000000000000; 68 | echo number2chinese($num2); // 两兆 69 | echo number2chinese($num2, true); // 贰兆元整 70 | $num3 = -1202030; 71 | echo number2chinese($num3); // 负一百二十万零两千零三十 72 | echo number2chinese($num3, true); // 负壹佰贰拾万零贰仟零叁拾元整 73 | ``` 74 | 75 | 当数字过大时,请输入string 76 | ```php 77 | $num2 = 1234567890.0123456789; 78 | echo number2chinese($num2); // 十二亿三千四百五十六万七千八百九十点零一二三 79 | echo number2chinese($num2, true); // 壹拾贰亿叁仟肆佰伍拾陆万柒仟捌佰玖拾元零壹分贰厘叁毫 80 | $num2 = '1234567890.0123456789'; 81 | echo number2chinese($num2); // 十二亿三千四百五十六万七千八百九十点零一二三四五六七八九 82 | echo number2chinese($num2, true); // 壹拾贰亿叁仟肆佰伍拾陆万柒仟捌佰玖拾元壹分贰厘叁毫 83 | ``` 84 | 85 | 若想精确小数点后两位,请先处理$num1 86 | ```php 87 | $num1 = 0.1234567890; 88 | echo number2chinese(number_format($num1, 2)); // 零点一二 89 | echo number2chinese(number_format($num1, 2), true); // 零元壹角贰分 90 | ``` 91 | 92 | ### 测试 93 | 94 | ``` 95 | php vendor/wilon/php-number2chinese/test.php // 随机一些数据进行测试 96 | php vendor/wilon/php-number2chinese/test.php 2000 // 指定数字 97 | ``` 98 | 99 | ______ 100 | 有问题?发issues 101 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wilon/php-number2chinese", 3 | "description": "PHP数字转为汉字描述、人民币大写方法。", 4 | "license": "MIT", 5 | "homepage": "https://wilon.github.io", 6 | "support": { 7 | "issues": "https://github.com/wilon/php-number2chinese/issues", 8 | "source": "https://github.com/wilon/php-number2chinese" 9 | }, 10 | "keywords": ["php", "number", "chinese"], 11 | "authors": [ 12 | { 13 | "name": "Weilong Wang", 14 | "email": "wilonx@163.com" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=5.4" 19 | }, 20 | "autoload": { 21 | "files": ["number2chinese.php"] 22 | }, 23 | "config": { 24 | "sort-packages": true 25 | }, 26 | "minimum-stability": "dev" 27 | } -------------------------------------------------------------------------------- /number2chinese.php: -------------------------------------------------------------------------------- 1 | https://github.com/wilon 10 | * 11 | */ 12 | 13 | if (! function_exists('number2chinese')) { 14 | 15 | /** 16 | * number2chinese description 17 | * 18 | * · 个,十,百,千,万,十万,百万,千万,亿,十亿,百亿,千亿,万亿,十万亿, 19 | * 百万亿,千万亿,兆;此函数亿乘以亿为兆 20 | * 21 | * · 以「十」开头,如十五,十万,十亿等。两位数以上,在数字中部出现,则用「一十几」, 22 | * 如一百一十,一千零一十,一万零一十等 23 | * 24 | * · 「二」和「两」的问题。两亿,两万,两千,两百,都可以,但是20只能是二十, 25 | * 200用二百也更好。22,2222,2222是「二十二亿两千二百二十二万两千二百二十二」 26 | * 27 | * · 关于「零」和「〇」的问题,数字中一律用「零」,只有页码、年代等编号中数的空位 28 | * 才能用「〇」。数位中间无论多少个0,都读成一个「零」。2014是「两千零一十四」, 29 | * 20014是「二十万零一十四」,201400是「二十万零一千四百」 30 | * 31 | * 参考:https://jingyan.baidu.com/article/636f38bb3cfc88d6b946104b.html 32 | * 33 | * 人民币写法参考:[正确填写票据和结算凭证的基本规定](http://bbs.chinaacc.com/forum-2-35/topic-1181907.html) 34 | * 35 | * @param mixed $number 36 | * @param boolean $isRmb 37 | * @return string 38 | */ 39 | function number2chinese($number, $isRmb = false) 40 | { 41 | // 判断正确数字 42 | if (!preg_match('/^-?\d+(\.\d+)?$/', $number)) { 43 | throw new Exception('number2chinese() wrong number', 1); 44 | } 45 | list($integer, $decimal) = explode('.', $number . '.0'); 46 | 47 | // 检测是否为负数 48 | $symbol = ''; 49 | if (substr($integer, 0, 1) == '-') { 50 | $symbol = '负'; 51 | $integer = substr($integer, 1); 52 | } 53 | if (preg_match('/^-?\d+$/', $number)) { 54 | $decimal = null; 55 | } 56 | $integer = ltrim($integer, '0'); 57 | 58 | // 准备参数 59 | $numArr = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '.' => '点']; 60 | $descArr = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万亿', '十', '百', '千', '兆', '十', '百', '千']; 61 | if ($isRmb) { 62 | $number = substr(sprintf("%.5f", $number), 0, -1); 63 | $numArr = ['', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '.' => '点']; 64 | $descArr = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万亿', '拾', '佰', '仟', '兆', '拾', '佰', '仟']; 65 | $rmbDescArr = ['角', '分', '厘', '毫']; 66 | } 67 | 68 | // 整数部分拼接 69 | $integerRes = ''; 70 | $count = strlen($integer); 71 | if ($count > max(array_keys($descArr))) { 72 | throw new Exception('number2chinese() number too large.', 1); 73 | } else if ($count == 0) { 74 | $integerRes = '零'; 75 | } else { 76 | for ($i = 0; $i < $count; $i++) { 77 | $n = $integer[$i]; // 位上的数 78 | $j = $count - $i - 1; // 单位数组 $descArr 的第几位 79 | // 零零的读法 80 | $isLing = $i > 1 // 去除首位 81 | && $n !== '0' // 本位数字不是零 82 | && $integer[$i - 1] === '0'; // 上一位是零 83 | $cnZero = $isLing ? '零': ''; 84 | $cnNum = $numArr[$n]; 85 | // 单位读法 86 | $isEmptyDanwei = ($n == '0' && $j % 4 != 0) // 是零且一断位上 87 | || substr($integer, $i - 3, 4) === '0000'; // 四个连续0 88 | $descMark = isset($cnDesc) ? $cnDesc : ''; 89 | $cnDesc = $isEmptyDanwei ? '' : $descArr[$j]; 90 | // 第一位是一十 91 | if ($i == 0 && $cnNum == '一' && $cnDesc == '十') $cnNum = ''; 92 | // 二两的读法 93 | $isChangeEr = $n > 1 && $cnNum == '二' // 去除首位 94 | && !in_array($cnDesc, ['', '十', '百']) // 不读两\两十\两百 95 | && $descMark !== '十'; // 不读十两 96 | if ($isChangeEr ) $cnNum = '两'; 97 | $integerRes .= $cnZero . $cnNum . $cnDesc; 98 | } 99 | } 100 | 101 | // 小数部分拼接 102 | $decimalRes = ''; 103 | $count = strlen($decimal ?? ''); 104 | if ($decimal === null) { 105 | $decimalRes = $isRmb ? '整' : ''; 106 | } else if ($decimal === '0') { 107 | $decimalRes = $isRmb ? '' : '零'; 108 | } else if ($count > max(array_keys($descArr))) { 109 | throw new Exception('number2chinese() number too large.', 1); 110 | } else { 111 | for ($i = 0; $i < $count; $i++) { 112 | if ($isRmb && $i > count($rmbDescArr) - 1) break; 113 | $n = $decimal[$i]; 114 | if (!$isRmb) { 115 | $cnZero = $n === '0' ? '零' : ''; 116 | $cnNum = $numArr[$n]; 117 | $cnDesc = ''; 118 | $decimalRes .= $cnZero . $cnNum . $cnDesc; 119 | } else { 120 | // 零零的读法 121 | $isLing = $i > 0 // 去除首位 122 | && $n !== '0' // 本位数字不是零 123 | && $decimal[$i - 1] === '0'; // 上一位是零 124 | $cnZero = $isLing ? '零' : ''; 125 | $cnNum = $numArr[$n]; 126 | $cnDesc = $cnNum ? $rmbDescArr[$i] : ''; 127 | $decimalRes .= $cnZero . $cnNum . $cnDesc; 128 | } 129 | } 130 | } 131 | // 拼接结果 132 | $res = $symbol . ( 133 | $isRmb 134 | ? $integerRes . ($decimalRes === '' ? '元整' : "元$decimalRes") 135 | : $integerRes . ($decimalRes ==='' ? '' : "点$decimalRes") 136 | ); 137 | return $res; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /test.php: -------------------------------------------------------------------------------- 1 | '; 7 | 8 | if (array_key_exists(1, $argv) && $num = $argv[1]) { 9 | echo $num, ' -> ', number2chinese($num), $br; 10 | echo "¥$num -> ", number2chinese($num, true), $br; 11 | die; 12 | } 13 | 14 | // 随机一些整数进行测试 15 | $num = ''; 16 | echo '随机一些整数进行测试:', $br; 17 | for ($i = 0; $i < 10; $i++) { 18 | $symbol = mt_rand(0, 9) < 5 ? '' : '-'; 19 | $num = $symbol . randNum($i); 20 | echo $num, ' -> ', number2chinese($num), $br; 21 | echo "¥$num -> ", number2chinese($num, true), $br; 22 | } 23 | 24 | echo $br; 25 | 26 | // 随机一些整数进行测试 27 | $num = ''; 28 | echo '随机一些小数进行测试:', $br; 29 | for ($i = 0; $i < 10; $i++) { 30 | $symbol = mt_rand(0, 9) < 5 ? '' : '-'; 31 | $num = $symbol . randNum($i) . '.' . randNum($i); 32 | $num = $num == '.' ? 0 : $num; 33 | echo $num, ' -> ', number2chinese($num), $br; 34 | echo "¥$num -> ", number2chinese($num, true), $br; 35 | } 36 | echo $br; 37 | 38 | // 验证测试 39 | $verify = [ 40 | '325.04' => [ 41 | '三百二十五点零四', 42 | '叁佰贰拾伍元零肆分', 43 | ], 44 | '1409.50' => [ 45 | '一千四百零九点五零', 46 | '壹仟肆佰零玖元伍角', 47 | ], 48 | '6007.14' => [ 49 | '六千零七点一四', 50 | '陆仟零柒元壹角肆分', 51 | ], 52 | '16409.02' => [ 53 | '一万六千四百零九点零二', 54 | '壹万陆仟肆佰零玖元零贰分', 55 | ], 56 | '107000.53' => [ 57 | '十万零七千点五三', 58 | '壹拾万零柒仟元伍角叁分', 59 | ], 60 | '646743393.06' => [ 61 | '六亿四千六百七十四万三千三百九十三点零六', 62 | '陆亿肆仟陆佰柒拾肆万叁仟叁佰玖拾叁元零陆分', 63 | ], 64 | ]; 65 | 66 | echo '验证测试:', $br; 67 | foreach ($verify as $num => $res) { 68 | $cn = number2chinese($num); 69 | $cnRmb = number2chinese($num, true); 70 | if ($cn != $res[0]) { 71 | echo "$num -> $cn {$res[0]} 错误!$br"; 72 | exit(1); 73 | } 74 | if ($cnRmb != $res[1]) { 75 | echo "¥$num -> $cnRmb {$res[1]} 错误!$br"; 76 | exit(1); 77 | } 78 | echo "正确! $num -> $cn $br"; 79 | echo "正确! ¥$num -> $cnRmb $br"; 80 | } 81 | 82 | 83 | 84 | function randNum($i) 85 | { 86 | $num = ''; 87 | for ($j = 0; $j < $i; $j++) { 88 | $num .= mt_rand(0, 9) > 3 ? mt_rand(0, 9) : 0; 89 | } 90 | $num = ltrim($num, '0'); 91 | return $num ?: 0; 92 | } 93 | --------------------------------------------------------------------------------