PHP数字转单词函数修复:11-19整数输出错误问题咨询
Fix for Integer 11-19 Conversion Issue in PHP Number-to-Words Function
Let's break down why your function is failing with numbers like 11-19 in the integer part, and fix it step by step.
The Root Cause
Your function works correctly for the decimal part because it checks if the entire decimal value is less than 20 first. But for the integer part, when processing segments (like the "212" in 4212), it splits two-digit numbers into tens and ones without checking if the tens digit is 1 (which should map to unique words like "Eleven" instead of "Ten One").
Fixed Code
<?php function toWords($num) { $ones = array( 0 => "Zero", 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", "014" => "Fourteen" ); $tens = array( 0 => "Zero", 1 => "Ten", 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 to 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, 1); $rettxt = ""; foreach ($whole_arr as $key => $i) { // Remove leading zeros while (substr($i, 0, 1) == "0") { $i = substr($i, 1, 5); } if (empty($i)) continue; // Skip empty segments after stripping zeros if ($i < 20) { $rettxt .= $ones[$i]; } elseif ($i < 100) { // Check if tens digit is 1 (11-19) $tens_digit = substr($i, 0, 1); $ones_digit = substr($i, 1, 1); if ($tens_digit == 1) { $rettxt .= $ones[$i]; // Use combined value like "Eleven" } else { $rettxt .= $tens[$tens_digit]; if ($ones_digit != "0") { $rettxt .= " ".$ones[$ones_digit]; } } } else { $hundreds_digit = substr($i, 0, 1); $last_two_digits = substr($i, 1, 2); if ($hundreds_digit != "0") { $rettxt .= $ones[$hundreds_digit]." ".$hundreds[0]; } // Handle last two digits: check if they're 11-19 if ($last_two_digits >= 11 && $last_two_digits <= 19) { $rettxt .= " ".$ones[$last_two_digits]; } else { $tens_digit = substr($last_two_digits, 0, 1); $ones_digit = substr($last_two_digits, 1, 1); if ($tens_digit != "0") { $rettxt .= " ".$tens[$tens_digit]; } if ($ones_digit != "0") { $rettxt .= " ".$ones[$ones_digit]; } } } if ($key > 0) { $rettxt .= " ".$hundreds[$key]." "; } } $rettxt = trim($rettxt)." Pesos"; if ($decnum > 0) { $rettxt .= " and "; if ($decnum < 20) { $rettxt .= $ones[$decnum]; } elseif ($decnum < 100) { $rettxt .= $tens[substr($decnum, 0, 1)]; $rettxt .= " ".$ones[substr($decnum, 1, 1)]; } $rettxt .= " Centavos"; } return $rettxt; } ?>
Key Fixes Made
- Two-digit integer segments: Added a check for when the tens digit is 1 (11-19) — instead of splitting into "Ten + One", we directly use the combined value from the
$onesarray (e.g., 12 → "Twelve"). - Three-digit integer segments: For the last two digits of a three-digit segment, we first check if they fall into 11-19. If yes, we use the combined word; otherwise, we split into tens and ones normally.
- Added empty segment check: Prevents extra spaces or words if a segment becomes empty after stripping leading zeros.
Test Results
- Input
4212→ Output:Four Thousand Two Hundred Twelve Pesos - Input
1917.18→ Output:One Thousand Nine Hundred Seventeen Pesos and Eighteen Centavos
内容的提问来源于stack exchange,提问作者SMCT - IT
相关产品推荐
相关产品推荐

