PHP数字转金额单词算法问题求助:dinars与millimes转换异常
PHP数字转金额单词算法修正
需求说明
- 输入小于1000(如999)时,输出应为「nine hundred and ninety-nine millimes」
- 输入大于999时,按1 dinar = 1000 millimes拆分输出:
- 输入1590 → 「one dinar and five hundred and ninety millimes」
- 输入275590 → 「two hundred and seventy-five dinars and five hundred and ninety millimes」
原代码问题
<?php function numtowords($num){ $decones = array( '01' => "One", '02' => "Two", '03' => "Three", '04' => "Four", '05' => "Five", '06' => "Six", '07' => "Seven", '08' => "Eight", '09' => "Nine", 10 => "Ten", 11 => "Eleven", 12 => "Twelve", 13 => "Thirteen", 14 => "Fourteen", 15 => "Fifteen", 16 => "Sixteen", 17 => "Seventeen", 18 => "Eighteen", 19 => "Nineteen" ); $ones = array( 0 => " ", 1 => "One", 2 => "Two", 3 => "Three", 4 => "Four", 5 => "Five", 6 => "Six", 7 => "Seven", 8 => "Eight", 9 => "Nine", 10 => "Ten", 11 => "Eleven", 12 => "Twelve", 13 => "Thirteen", 14 => "Fourteen", 15 => "Fifteen", 16 => "Sixteen", 17 => "Seventeen", 18 => "Eighteen", 19 => "Nineteen" ); $tens = array( 0 => "", 2 => "Twenty", 3 => "Thirty", 4 => "Forty", 5 => "Fifty", 6 => "Sixty", 7 => "Seventy", 8 => "Eighty", 9 => "Ninety" ); $hundreds = array( "Hundred", "Thousand", "Million", "Billion", "Trillion", "Quadrillion" ); //limit t quadrillion $num = number_format($num,2,".",","); $num_arr = explode(".",$num); $wholenum = $num_arr[0]; $decnum = $num_arr[1]; $whole_arr = array_reverse(explode(",",$wholenum)); krsort($whole_arr); $rettxt = ""; foreach($whole_arr as $key => $i){ if($i < 20){ $rettxt .= $ones[$i]; } elseif($i < 100){ $rettxt .= $tens[substr($i,0,1)]; $rettxt .= " ".$ones[substr($i,1,1)]; } else{ $rettxt .= $ones[substr($i,0,1)]." ".$hundreds[0]; $rettxt .= " ".$tens[substr($i,1,1)]; $rettxt .= " ".$ones[substr($i,2,1)]; } if($key > 0){ $rettxt .= " ".$hundreds[$key]." "; } } $rettxt = $rettxt." dinar/s"; if($decnum > 0){ $rettxt .= " and "; if($decnum < 20){ $rettxt .= $decones[$decnum]; } elseif($decnum < 1000){ $rettxt .= $tens[substr($decnum,0,1)]; $rettxt .= " ".$ones[substr($decnum,1,1)]; } $rettxt = $rettxt." FRANK/s"; } return $rettxt; } echo numtowords(275,590); ?>
原代码核心问题:
- 传参错误:调用
numtowords(275,590)传入两个参数,实际应传单个数字275590 - 金额拆分逻辑错误:错误用
number_format转小数格式,未按1 dinar=1000 millimes拆分整数与余数 - 格式缺失:未处理百位与十位间的"and"、十位与个位的连字符(如
ninety-nine) - 复数错误:硬编码
dinar/s和FRANK/s,不符合需求的dinars和millimes - 大小写不匹配:数组单词首字母大写,需求输出全小写
- 三位数处理遗漏:millimes可能为0-999,但原代码仅处理两位数
修正后的代码
<?php function numberToWords($num) { // 转为整数避免小数问题 $num = (int)$num; // 小写单词表 $ones = [ '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen' ]; $tens = [ '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety' ]; // 处理0-999转单词的通用函数 function convertThreeDigits($n) { global $ones, $tens; $str = ''; // 处理百位 if ($n >= 100) { $str .= $ones[floor($n / 100)] . ' hundred'; $n %= 100; if ($n > 0) { $str .= ' and '; } } // 处理十位和个位 if ($n > 0) { if ($n < 20) { $str .= $ones[$n]; } else { $str .= $tens[floor($n / 10)]; $remainder = $n % 10; if ($remainder > 0) { $str .= '-' . $ones[$remainder]; } } } return trim($str); } // 拆分dinar和millimes $dinar = floor($num / 1000); $millimes = $num % 1000; $result = []; // 处理dinar部分 if ($dinar > 0) { $dinarStr = convertThreeDigits($dinar); $dinarStr .= $dinar > 1 ? ' dinars' : ' dinar'; $result[] = $dinarStr; } // 处理millimes部分 $millimesStr = convertThreeDigits($millimes); if ($num < 1000 || $millimes > 0) { $millimesStr .= ' millimes'; $result[] = $millimesStr; } // 用"and"连接两部分 return implode(' and ', $result); } // 测试案例 echo numberToWords(999) . "\n"; // nine hundred and ninety-nine millimes echo numberToWords(1590) . "\n"; // one dinar and five hundred and ninety millimes echo numberToWords(275590) . "\n"; // two hundred and seventy-five dinars and five hundred and ninety millimes ?>
关键修改说明
- 金额拆分逻辑:通过
floor($num/1000)和$num%1000拆分dinar与millimes,符合单位换算规则 - 通用转换函数:封装
convertThreeDigits处理0-999的单词转换,自动添加"and"和连字符 - 复数处理:dinar数量>1时用
dinars,millimes始终用复数形式 - 格式统一:所有单词用小写,匹配需求输出
- 传参修复:调用时传入单个整数,避免参数错误
内容的提问来源于stack exchange,提问作者med amine eddine khadhraoui
相关产品推荐
相关产品推荐

