В PHP есть простой способ преобразования числа в слово? Например, от 27 до 27 .
Я нашел некоторый (2007/2008) исходный код онлайн и, поскольку это авторское право, но я могу использовать его свободно и изменять его, но я хочу, поэтому я размещаю его здесь и переиздаю под CC-Wiki:
<?php /** * English Number Converter - Collection of PHP functions to convert a number * into English text. * * This exact code is licensed under CC-Wiki on Stackoverflow. * http://creativecommons.org/licenses/by-sa/3.0/ * * @link http://stackoverflow.com/q/277569/367456 * @question Is there an easy way to convert a number to a word in PHP? * * This file incorporates work covered by the following copyright and * permission notice: * * Copyright 2007-2008 Brenton Fletcher. http://bloople.net/num2text * You can use this freely and modify it however you want. */ function convertNumber($number) { list($integer, $fraction) = explode(".", (string) $number); $output = ""; if ($integer{0} == "-") { $output = "negative "; $integer = ltrim($integer, "-"); } else if ($integer{0} == "+") { $output = "positive "; $integer = ltrim($integer, "+"); } if ($integer{0} == "0") { $output .= "zero"; } else { $integer = str_pad($integer, 36, "0", STR_PAD_LEFT); $group = rtrim(chunk_split($integer, 3, " "), " "); $groups = explode(" ", $group); $groups2 = array(); foreach ($groups as $g) { $groups2[] = convertThreeDigit($g{0}, $g{1}, $g{2}); } for ($z = 0; $z < count($groups2); $z++) { if ($groups2[$z] != "") { $output .= $groups2[$z] . convertGroup(11 - $z) . ( $z < 11 && !array_search('', array_slice($groups2, $z + 1, -1)) && $groups2[11] != '' && $groups[11]{0} == '0' ? " and " : ", " ); } } $output = rtrim($output, ", "); } if ($fraction > 0) { $output .= " point"; for ($i = 0; $i < strlen($fraction); $i++) { $output .= " " . convertDigit($fraction{$i}); } } return $output; } function convertGroup($index) { switch ($index) { case 11: return " decillion"; case 10: return " nonillion"; case 9: return " octillion"; case 8: return " septillion"; case 7: return " sextillion"; case 6: return " quintrillion"; case 5: return " quadrillion"; case 4: return " trillion"; case 3: return " billion"; case 2: return " million"; case 1: return " thousand"; case 0: return ""; } } function convertThreeDigit($digit1, $digit2, $digit3) { $buffer = ""; if ($digit1 == "0" && $digit2 == "0" && $digit3 == "0") { return ""; } if ($digit1 != "0") { $buffer .= convertDigit($digit1) . " hundred"; if ($digit2 != "0" || $digit3 != "0") { $buffer .= " and "; } } if ($digit2 != "0") { $buffer .= convertTwoDigit($digit2, $digit3); } else if ($digit3 != "0") { $buffer .= convertDigit($digit3); } return $buffer; } function convertTwoDigit($digit1, $digit2) { if ($digit2 == "0") { switch ($digit1) { case "1": return "ten"; case "2": return "twenty"; case "3": return "thirty"; case "4": return "forty"; case "5": return "fifty"; case "6": return "sixty"; case "7": return "seventy"; case "8": return "eighty"; case "9": return "ninety"; } } else if ($digit1 == "1") { switch ($digit2) { case "1": return "eleven"; case "2": return "twelve"; case "3": return "thirteen"; case "4": return "fourteen"; case "5": return "fifteen"; case "6": return "sixteen"; case "7": return "seventeen"; case "8": return "eighteen"; case "9": return "nineteen"; } } else { $temp = convertDigit($digit2); switch ($digit1) { case "2": return "twenty-$temp"; case "3": return "thirty-$temp"; case "4": return "forty-$temp"; case "5": return "fifty-$temp"; case "6": return "sixty-$temp"; case "7": return "seventy-$temp"; case "8": return "eighty-$temp"; case "9": return "ninety-$temp"; } } } function convertDigit($digit) { switch ($digit) { case "0": return "zero"; case "1": return "one"; case "2": return "two"; case "3": return "three"; case "4": return "four"; case "5": return "five"; case "6": return "six"; case "7": return "seven"; case "8": return "eight"; case "9": return "nine"; } }
Кроме того, вы можете использовать класс NumberFormatter из пакета intl
в PHP. Вот пример кода, чтобы вы начали (для командной строки):
<?php if ($argc < 3) { echo "usage: php {$argv[0]} lang-tag number ...\n"; exit; } array_shift($argv); $lang_tag = array_shift($argv); $nf1 = new NumberFormatter($lang_tag, NumberFormatter::DECIMAL); $nf2 = new NumberFormatter($lang_tag, NumberFormatter::SPELLOUT); foreach ($argv as $num) { echo $nf1->format($num).' is '.$nf2->format($num)."\n"; }
В PECL Numbers_Words
пакет Numbers_Words
. Он делает именно то, о чем вы просите. Поддерживаются следующие языки:
Для этого я нашел две ссылки. Первый – бесплатный PHP-класс, который вы могли бы использовать, вторая – это примерная функция, которую вы могли бы просмотреть и скопировать или использовать, чтобы написать свой собственный.
Нет никакого встроенного способа, о котором я знаю, но если вы посмотрите на мой пример кода для этого вопроса (на C #), вам должно быть достаточно легко, чтобы вы могли работать. В основном, это просто вопрос смены титров переменных и добавление префикса $
где это необходимо, и он должен работать.
Я переписал вышеприведенный код, чтобы он соответствовал стандартным форматам номеров американских письменных номеров.
function singledigit($number){ switch($number){ case 0:$word = "zero";break; case 1:$word = "one";break; case 2:$word = "two";break; case 3:$word = "three";break; case 4:$word = "four";break; case 5:$word = "five";break; case 6:$word = "six";break; case 7:$word = "seven";break; case 8:$word = "eight";break; case 9:$word = "nine";break; } return $word; } function doubledigitnumber($number){ if($number == 0){ $word = ""; } else{ $word = "-".singledigit($number); } return $word; } function doubledigit($number){ switch($number[0]){ case 0:$word = doubledigitnumber($number[1]);break; case 1: switch($number[1]){ case 0:$word = "ten";break; case 1:$word = "eleven";break; case 2:$word = "twelve";break; case 3:$word = "thirteen";break; case 4:$word = "fourteen";break; case 5:$word = "fifteen";break; case 6:$word = "sixteen";break; case 7:$word = "seventeen";break; case 8:$word = "eighteen";break; case 9:$word = "ninteen";break; }break; case 2:$word = "twenty".doubledigitnumber($number[1]);break; case 3:$word = "thirty".doubledigitnumber($number[1]);break; case 4:$word = "forty".doubledigitnumber($number[1]);break; case 5:$word = "fifty".doubledigitnumber($number[1]);break; case 6:$word = "sixty".doubledigitnumber($number[1]);break; case 7:$word = "seventy".doubledigitnumber($number[1]);break; case 8:$word = "eighty".doubledigitnumber($number[1]);break; case 9:$word = "ninety".doubledigitnumber($number[1]);break; } return $word; } function unitdigit($numberlen,$number){ switch($numberlen){ case 3:case 6:case 9:case 12:$word = "hundred";break; case 4:case 5:$word = "thousand";break; case 7:case 8:$word = "million";break; case 10:case 11:$word = "billion";break; } return $word; } function numberToWord($number){ $numberlength = strlen($number); if ($numberlength == 1) { return singledigit($number); }elseif ($numberlength == 2) { return doubledigit($number); } else { $word = ""; $wordin = ""; switch ($numberlength ) { case 5:case 8: case 11: if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = doubledigit($number[0].$number[1]) ." ".$unitdigit." "; return $word." ".numberToWord(substr($number,2)); } else{ return $word." ".numberToWord(substr($number,1)); } break; default: if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = singledigit($number[0]) ." ".$unitdigit." "; } return $word." ".numberToWord(substr($number,1)); } } }
Мне понадобилось решение, которое помещало «и» в возвращаемую строку и отформатировало ее в предложение – как правило, так говорит человек. Поэтому я немного адаптировал другое решение – отправил, поскольку я думал, что это может быть полезно для кого-то.
4,835,301 returns "Four million eight hundred and thirty five thousand three hundred and one."
Код
function convertNumber($num = false) { $num = str_replace(array(',', ''), '' , trim($num)); if(! $num) { return false; } $num = (int) $num; $words = array(); $list1 = array('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen' ); $list2 = array('', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety', 'hundred'); $list3 = array('', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion', 'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion', 'vigintillion' ); $num_length = strlen($num); $levels = (int) (($num_length + 2) / 3); $max_length = $levels * 3; $num = substr('00' . $num, -$max_length); $num_levels = str_split($num, 3); for ($i = 0; $i < count($num_levels); $i++) { $levels--; $hundreds = (int) ($num_levels[$i] / 100); $hundreds = ($hundreds ? ' ' . $list1[$hundreds] . ' hundred' . ( $hundreds == 1 ? '' : '' ) . ' ' : ''); $tens = (int) ($num_levels[$i] % 100); $singles = ''; if ( $tens < 20 ) { $tens = ($tens ? ' and ' . $list1[$tens] . ' ' : '' ); } elseif ($tens >= 20) { $tens = (int)($tens / 10); $tens = ' and ' . $list2[$tens] . ' '; $singles = (int) ($num_levels[$i] % 10); $singles = ' ' . $list1[$singles] . ' '; } $words[] = $hundreds . $tens . $singles . ( ( $levels && ( int ) ( $num_levels[$i] ) ) ? ' ' . $list3[$levels] . ' ' : '' ); } //end for loop $commas = count($words); if ($commas > 1) { $commas = $commas - 1; } $words = implode(' ', $words); $words = preg_replace('/^\s\b(and)/', '', $words ); $words = trim($words); $words = ucfirst($words); $words = $words . "."; return $words; }
Вот небольшой класс, который я написал сегодня вечером. Предостережения:
longform
не обрабатывает десятичные числа. Он просто стирает их. Не стесняйтесь изменять это и добавлять эту функциональность, если хотите. numberformat
делает десятичные знаки, но не делает никакого округления. Мне пришлось создать новую функцию numberformat
из-за присущих PHP ограничений с целыми размерами. Я переводил числа настолько большие, что, когда я использовал number_format()
чтобы проверить мои переводы, мне потребовалось 30 минут, чтобы понять, что мои переводы не были неправильными, number_format
был. 2,147,483,647
(2 миллиарда и изменение). 64-разрядные версии будут обрабатывать до 9 quintillion
или что-то в этом роде. НО это не имеет значения здесь, пока вы longform
методу longform
в виде string
. Я сделал 306-значный номер над ajax
из веб-формы просто отлично, пока я передал его серверу как ''+number
. Таким образом, этот класс будет переводить числа до 999 Centillion, 999 etc.
(Например, строка длиной 9s 306 символов). Любое число больше, чем это, и функция просто возвращает немое сообщение.
Применение:
$number = '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999'; reallyBig::longform($number);
Необязательный второй логический параметр по умолчанию равен true, который добавляет запятую, насколько это возможно в нужном месте, чтобы сделать число более читаемым.
Кстати, вы можете поставить a -
на фронт, если хотите, чтобы он был отрицательным, но любые другие символы, включенные в введенную строку, будут удалены. Например:
reallyBig::longform('-C55LL-M5-4-a-9u7-71m3-M8');
полной reallyBig::longform('-C55LL-M5-4-a-9u7-71m3-M8');
выйдет: negative five billion, five hundred fifty-four million, nine hundred seventy-seven thousand, one hundred thirty-eight
Метод numberformat
не нужен ни для какого другого метода. Это просто, если вы хотите проверить действительно длинный переведенный номер. Поскольку все эти функции обрабатывают числа как строки, они не сталкиваются с ограничениями PHP.
Единственная причина, по которой я остановился на уровне 999 центнеров, – это то, что на сайте, на который я смотрел, был последним номером, когда я не мог вспомнить, что произошло после дециллиона.
class reallyBig { private static $map, $strings; private static function map() { $map = array(); $num = 1; $count = 1; while($num < 307) { if($count == 1) $map[$num] = $num+2; elseif($count == 2) $map[$num] = $num+1; else { $map[$num] = $num; $count = 0; } $count++; $num++; } return $map; } private static function strings() { return array ( 6 => 'thousand', 9 => 'million', 12 => 'billion', 15 => 'trillion', 18 => 'quadrillion', 21 => 'quintillion', 24 => 'sextillion', 27 => 'septillion', 30 => 'octillion', 33 => 'nonillion', 36 => 'decillion', 39 => 'undecillion', 42 => 'duodecillion', 45 => 'tredecillion', 48 => 'quattuordecillion', 51 => 'quindecillion', 54 => 'sexdecillion', 57 => 'septendecillion', 60 => 'octodecillion', 63 => 'novemdecillion', 66 => 'vigintillion', 69 => 'unvigintillion', 72 => 'duovigintillion', 75 => 'trevigintillion', 78 => 'quattuorvigintillion', 81 => 'quinvigintillion', 84 => 'sexvigintillion', 87 => 'septenvigintillion', 90 => 'octovigintillion', 93 => 'novemvigintillion', 96 => 'trigintillion', 99 => 'untrigintillion', 102 => 'duotrigintillion', 105 => 'tretrigintillion', 108 => 'quattuortrigintillion', 111 => 'quintrigintillion', 114 => 'sextrigintillion', 117 => 'septentrigintillion', 120 => 'octotrigintillion', 123 => 'novemtrigintillion', 126 => 'quadragintillion', 129 => 'unquadragintillion', 132 => 'duoquadragintillion', 135 => 'trequadragintillion', 138 => 'quattuorquadragintillion', 141 => 'quinquadragintillion', 144 => 'sexquadragintillion', 147 => 'septenquadragintillion', 150 => 'octoquadragintillion', 153 => 'novemquadragintillion', 156 => 'quinquagintillion', 159 => 'unquinquagintillion', 162 => 'duoquinquagintillion', 165 => 'trequinquagintillion', 168 => 'quattuorquinquagintillion', 171 => 'quinquinquagintillion', 174 => 'sexquinquagintillion', 177 => 'septenquinquagintillion', 180 => 'octoquinquagintillion', 183 => 'novemquinquagintillion', 186 => 'sexagintillion', 189 => 'unsexagintillion', 192 => 'duosexagintillion', 195 => 'tresexagintillion', 198 => 'quattuorsexagintillion', 201 => 'quinsexagintillion', 204 => 'sexsexagintillion', 207 => 'septensexagintillion', 210 => 'octosexagintillion', 213 => 'novemsexagintillion', 216 => 'septuagintillion', 219 => 'unseptuagintillion', 222 => 'duoseptuagintillion', 225 => 'treseptuagintillion', 228 => 'quattuorseptuagintillion', 231 => 'quinseptuagintillion', 234 => 'sexseptuagintillion', 237 => 'septenseptuagintillion', 240 => 'octoseptuagintillion', 243 => 'novemseptuagintillion', 246 => 'octogintillion', 249 => 'unoctogintillion', 252 => 'duooctogintillion', 255 => 'treoctogintillion', 258 => 'quattuoroctogintillion', 261 => 'quinoctogintillion', 264 => 'sexoctogintillion', 267 => 'septenoctogintillion', 270 => 'octooctogintillion', 273 => 'novemoctogintillion', 276 => 'nonagintillion', 279 => 'unnonagintillion', 282 => 'duononagintillion', 285 => 'trenonagintillion', 288 => 'quattuornonagintillion', 291 => 'quinnonagintillion', 294 => 'sexnonagintillion', 297 => 'septennonagintillion', 300 => 'octononagintillion', 303 => 'novemnonagintillion', 306 => 'centillion', ); } public static function longform($number = string, $commas = true) { $negative = substr($number, 0, 1) == '-' ? 'negative ' : ''; list($number) = explode('.', $number); $number = trim(preg_replace("/[^0-9]/u", "", $number)); $number = (string)(ltrim($number,'0')); if(empty($number)) return 'zero'; $length = strlen($number); if($length < 2) return $negative.self::ones($number); if($length < 3) return $negative.self::tens($number); if($length < 4) return $commas ? $negative.str_replace('hundred ', 'hundred and ', self::hundreds($number)) : $negative.self::hundreds($number); if($length < 307) { self::$map = self::map(); self::$strings = self::strings(); $result = self::beyond($number, self::$map[$length]); if(!$commas) return $negative.$result; $strings = self::$strings; $thousand = array_shift($strings); foreach($strings as $string) $result = str_replace($string.' ', $string.', ', $result); if(strpos($result, 'thousand') !== false) list($junk,$remainder) = explode('thousand', $result); else $remainder = $result; return strpos($remainder, 'hundred') !== false ? $negative.str_replace('thousand ', 'thousand, ', $result) : $negative.str_replace('thousand ', 'thousand and ', $result); } return 'a '.$negative.'number too big for your britches'; } private static function ones($number) { $ones = array('zero','one','two','three','four','five','six','seven','eight','nine'); return $ones[$number]; } private static function tens($number) { $number = (string)(ltrim($number,'0')); if(strlen($number) < 2) return self::ones($number); if($number < 20) { $teens = array('ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'); return $teens[($number-10)]; } else { $tens = array('','','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety'); $word = $tens[$number[0]]; return empty($number[1]) ? $word : $word.'-'.self::ones($number[1]); } } private static function hundreds($number) { $number = (string)(ltrim($number,'0')); if(strlen($number) < 3) return self::tens($number); $word = self::ones($number[0]).' hundred'; $remainder = substr($number, -2); if(ltrim($remainder,'0') != '') $word .= ' '.self::tens($remainder); return $word; } private static function beyond($number, $limit) { $number = (string)(ltrim($number,'0')); $length = strlen($number); if($length < 4) return self::hundreds($number); if($length < ($limit-2)) return self::beyond($number, self::$map[($limit-3)]); if($length == $limit) $word = self::hundreds(substr($number, 0, 3), true); elseif($length == ($limit-1)) $word = self::tens(substr($number, 0, 2)); else $word = self::ones($number[0]); $word .= ' '.self::$strings[$limit]; $sub = ($limit-3); $remainder = substr($number, -$sub); if(ltrim($remainder,'0') != '') $word .= ' '.self::beyond($remainder, self::$map[$sub]); return $word; } public static function numberformat($number, $fixed = 0, $dec = '.', $thou = ',') { $negative = substr($number, 0, 1) == '-' ? '-' : ''; $number = trim(preg_replace("/[^0-9\.]/u", "", $number)); $number = (string)(ltrim($number,'0')); $fixed = (int)$fixed; if(!is_numeric($fixed)) $fixed = 0; if(strpos($number, $dec) !== false) list($number,$decimals) = explode($dec, $number); else $decimals = '0'; if($fixed) $decimals = '.'.str_pad(substr($decimals, 0, $fixed), $fixed, 0, STR_PAD_RIGHT); else $decimals = ''; $thousands = array_map('strrev', array_reverse(str_split(strrev($number), 3))); return $negative.implode($thou,$thousands).$decimals; } }
Amount in Words:</b><?=no_to_words($number)?>
Очень простой способ преобразования числа в слова с использованием функции PHP.
Я сгенерировал это с помощью рекурсивной функции.
$wordnum = numberToWord($number); echo $wordnum."<BR>"; function singledigit($number){ switch($number){ case 0:$word = "zero";break; case 1:$word = "One";break; case 2:$word = "two";break; case 3:$word = "three";break; case 4:$word = "Four";break; case 5:$word = "Five";break; case 6:$word = "Six";break; case 7:$word = "Seven";break; case 8:$word = "Eight";break; case 9:$word = "Nine";break; } return $word; } function doubledigitnumber($number){ if($number == 0){ $word = ""; } else{ $word = singledigit($number); } return $word; } function doubledigit($number){ switch($number[0]){ case 0:$word = doubledigitnumber($number[1]);break; case 1: switch($number[1]){ case 0:$word = "Ten";break; case 1:$word = "Eleven";break; case 2:$word = "Twelve";break; case 3:$word = "Thirteen";break; case 4:$word = "Fourteen";break; case 5:$word = "Fifteen";break; case 6:$word = "Sixteen";break; case 7:$word = "Seventeen";break; case 8:$word = "Eighteen";break; case 9:$word = "Ninteen";break; }break; case 2:$word = "Twenty".doubledigitnumber($number[1]);break; case 3:$word = "Thirty".doubledigitnumber($number[1]);break; case 4:$word = "Forty".doubledigitnumber($number[1]);break; case 5:$word = "Fifty".doubledigitnumber($number[1]);break; case 6:$word = "Sixty".doubledigitnumber($number[1]);break; case 7:$word = "Seventy".doubledigitnumber($number[1]);break; case 8:$word = "Eighty".doubledigitnumber($number[1]);break; case 9:$word = "Ninety".doubledigitnumber($number[1]);break; } return $word; } function unitdigit($numberlen,$number){ switch($numberlen){ case 3:$word = "Hundred";break; case 4:$word = "Thousand";break; case 5:$word = "Thousand";break; case 6:$word = "Lakh";break; case 7:$word = "Lakh";break; case 8:$word = "Crore";break; case 9:$word = "Crore";break; } return $word; } function numberToWord($number){ $numberlength = strlen($number); if ($numberlength == 1) { return singledigit($number); }elseif ($numberlength == 2) { return doubledigit($number); } else { $word = ""; $wordin = ""; if($numberlength == 9){ if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = doubledigit($number[0].$number[1]) ." ".$unitdigit." "; return $word." ".numberToWord(substr($number,2)); } else{ return $word." ".numberToWord(substr($number,1)); } } if($numberlength == 7){ if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = doubledigit($number[0].$number[1]) ." ".$unitdigit." "; return $word." ".numberToWord(substr($number,2)); } else{ return $word." ".numberToWord(substr($number,1)); } } if($numberlength == 5){ if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = doubledigit($number[0].$number[1]) ." ".$unitdigit." "; return $word." ".numberToWord(substr($number,2)); } else{ return $word." ".numberToWord(substr($number,1)); } } else{ if($number[0] >0){ $unitdigit = unitdigit($numberlength,$number[0]); $word = singledigit($number[0]) ." ".$unitdigit." "; } return $word." ".numberToWord(substr($number,1)); } } }