Вывести число прописью php
БлогNot. PHP: число прописью по-русски
PHP: число прописью по-русски
Классическая задача, которую программисты всё решают и решают (1234 -> «одна тысяча двести тридцать четыре» и т.п.). Правда, для русского языка нужно делать всё несколько нетривиально:
- разбить число на тройки цифр справа налево;
- каждую тройку обрабатывать отдельно, в частности, насовать между ними слова, обозначающие разряды (тысяча, миллион, и т.д.);
- учесть, что как одно и то же число, так и слова, обозначающие разряды, могут писаться по-разному (две тысячи, пять тысяч, два миллиона, пять миллионов и т.д.).
Функция numberToRussian , показанная ниже, пытается всё это учесть.
Целое число на входе функции может быть как положительным, так и отрицательным. Названия выводятся по принятой в России короткой шкале именования чисел. Чтобы не зависеть от максимально допустимого в вашей системе целого значения PHP_INT_MAX , лучше передавать в функцию строковую запись числа, тогда можно получить прописи чисел вплоть до 10 в 33 степени. Числа ещё больше обозначены только что изобретённой мною константой «дофигальон» 🙂 Ну или возьмите нужные для массива $degrees названия степеней «десятки» по последней ссылке, там до 10 в 99 степени.
Оболочку-сервис для функции писать лень, подобных кодов в блоге уже много.
Все тесты видны внизу листинга, а вот и он сам:
Проверено на локалхосте «Денвер» в 64-битной системе со старым добрым PHP 5.3.13, на выдаче вот что (с точностью до разметки):
Значение=-11111112, результат преобразования=минус одиннадцать миллионов сто одиннадцать тысяч сто двенадцать
Значение=2147483647, результат преобразования=два миллиарда сто сорок семь миллионов четыреста восемьдесят три тысячи шестьсот сорок семь
Значение=9.2233720368548E+18, результат преобразования=девять квинтиллионов двадцать два квадриллиона триста тридцать семь триллионов двести три миллиарда шестьсот восемьдесят пять миллионов четыреста восемьдесят тысяч восемнадцать
Значение=9223372036854775807, результат преобразования=девять квинтиллионов двести двадцать три квадриллиона триста семьдесят два триллиона тридцать шесть миллиардов восемьсот пятьдесят четыре миллиона семьсот семьдесят пять тысяч восемьсот семь
Значение=-999999999999999999999999999999999999, результат преобразования=минус девятьсот девяносто девять дециллионов девятьсот девяносто девять нониллионов девятьсот девяносто девять октиллионов девятьсот девяносто девять септиллионов девятьсот девяносто девять секстиллионов девятьсот девяносто девять квинтиллионов девятьсот девяносто девять квадриллионов девятьсот девяносто девять триллионов девятьсот девяносто девять миллиардов девятьсот девяносто девять миллионов девятьсот девяносто девять тысяч девятьсот девяносто девять
Значение=1000000000000000000000000000000000000, результат преобразования=один дофигальон
Обратите внимание на комментарии в листинге, почему «не вышло» с числом 9223372036854775807.
Допустимыми числами на входе функции являются, вообще говоря, строки шаблона
то есть, необязательный знак «-» в первой позиции плюс не более 36 десятичных цифр.
Источник
Число прописью средствами PHP
В статье рассмотрен пример функции на языке PHP, формирующей числительные для использования с существительными мужского и женского рода. Такая функция может пригодиться для автоматического формирования счетов, договоров, актов или сообщений на сайте. На оригинальность или новизну не претендую, очевидно, что аналигичные решения существуют давно.
В русском языке существительное, употребляемое вместе с числительным, имеет три формы. Рассмотрим пример:
- один друг
- два друга
- три друга
- четыре друга
- пять друзей
- .
- сто один друг.
Мы видим, что три различных формы существительного отвечают числительным 1,2 и 5. Кроме того, числительные для существительных женского рода другие, см. пример ниже:
- одна подруга
- две подруги
- три подруги
- четыре подруги
- пять подруг
- .
- сто одна подруга.
Женский род числительных требуется даже для описания существительных мужского рода, так как слово «тысяча» — слово женского рода.
Функция written_number(), приведенная ниже, имеет два аргумента. Первый аргумент — целое неотрицательное число (меньше миллиарда), второй — род (0 — мужской, 1 женский).
global $N0 , $Ne0 , $Ne1 , $Ne2 , $Ne3 , $Ne6 ;
$Ne0 = array (
0 => array ( » , ‘один’ , ‘два’ , ‘три’ , ‘четыре’ , ‘пять’ , ‘шесть’ ,
‘семь’ , ‘восемь’ , ‘девять’ , ‘десять’ , ‘одиннадцать’ ,
‘двенадцать’ , ‘тринадцать’ , ‘четырнадцать’ , ‘пятнадцать’ ,
‘шестнадцать’ , ‘семнадцать’ , ‘восемнадцать’ , ‘девятнадцать’ ) ,
1 => array ( » , ‘одна’ , ‘две’ , ‘три’ , ‘четыре’ , ‘пять’ , ‘шесть’ ,
‘семь’ , ‘восемь’ , ‘девять’ , ‘десять’ , ‘одиннадцать’ ,
‘двенадцать’ , ‘тринадцать’ , ‘четырнадцать’ , ‘пятнадцать’ ,
‘шестнадцать’ , ‘семнадцать’ , ‘восемнадцать’ , ‘девятнадцать’ )
) ;
$Ne1 = array ( » , ‘десять’ , ‘двадцать’ , ‘тридцать’ , ‘сорок’ , ‘пятьдесят’ ,
‘шестьдесят’ , ‘семьдесят’ , ‘восемьдесят’ , ‘девяносто’ ) ;
$Ne2 = array ( » , ‘сто’ , ‘двести’ , ‘триста’ , ‘четыреста’ , ‘пятьсот’ ,
‘шестьсот’ , ‘семьсот’ , ‘восемьсот’ , ‘девятьсот’ ) ;
$Ne3 = array ( 1 => ‘тысяча’ , 2 => ‘тысячи’ , 5 => ‘тысяч’ ) ;
$Ne6 = array ( 1 => ‘миллион’ , 2 => ‘миллиона’ , 5 => ‘миллионов’ ) ;
function written_number ( $i , $female = false ) <
global $N0 ;
if ( ( $i 0 ) || ( $i >=1e9 ) || ! is_int ( $i ) ) <
return false ; // Аргумент должен быть неотрицательным целым числом, не превышающим 1 миллион
>
if ( $i == 0 ) <
return $N0 ;
>
else <
return preg_replace ( array ( ‘/s+/’ , ‘/ \s $/’ ) ,
array ( ‘ ‘ , » ) ,
num1e9 ( $i , $female ) ) ;
return num1e9 ( $i , $female ) ;
>
>
function num_125 ( $n ) <
/* форма склонения слова, существительное с числительным склоняется
одним из трех способов: 1 миллион, 2 миллиона, 5 миллионов */
$n100 = $n % 100 ;
$n10 = $n % 10 ;
if ( ( $n100 > 10 ) && ( $n100 20 ) ) <
return 5 ;
>
elseif ( $n10 == 1 ) <
return 1 ;
>
elseif ( ( $n10 >= 2 ) && ( $n10 4 ) ) <
return 2 ;
>
else <
return 5 ;
>
>
function num1e9 ( $i , $female ) <
global $Ne6 ;
if ( $i ) <
return num1e6 ( $i , $female ) ;
>
else <
return num1000 ( intval ( $i /1e6 ) , false ) . ‘ ‘ .
$Ne6 [ num_125 ( intval ( $i /1e6 ) ) ] . ‘ ‘ . num1e6 ( $i %1e6, $female ) ;
>
>
function num1e6 ( $i , $female ) <
global $Ne3 ;
if ( $i 1000 ) <
return num1000 ( $i , $female ) ;
>
else <
return num1000 ( intval ( $i / 1000 ) , true ) . ‘ ‘ .
$Ne3 [ num_125 ( intval ( $i / 1000 ) ) ] . ‘ ‘ . num1000 ( $i % 1000 , $female ) ;
>
>
function num1000 ( $i , $female ) <
global $Ne2 ;
if ( $i 100 ) <
return num100 ( $i , $female ) ;
>
else <
return $Ne2 [ intval ( $i / 100 ) ] . ( ( $i % 100 ) ? ( ‘ ‘ . num100 ( $i % 100 , $female ) ) : » ) ;
>
>
function num100 ( $i , $female ) <
global $Ne0 , $Ne1 ;
$gender = $female ? 1 : 0 ;
if ( $i 20 ) <
return $Ne0 [ $gender ] [ $i ] ;
>
else <
return $Ne1 [ intval ( $i / 10 ) ] . ( ( $i % 10 ) ? ( ‘ ‘ . $Ne0 [ $gender ] [ $i % 10 ] ) : » ) ;
>
>
Рассмотрим примеры использования функции written_number():
Статья написана по материалам онлайн-курса «Программирование на PHP».
|
Выведет:
У пользователя одиннадцать друзей и одна тысяча ноль подруг
Ответить
05.05.2008, 02:08 Ответить |
rgbeastdie() в функции written_number() стояла скорее как маркер, чем как функциональная возможность, заменил die() на return false. Скрипт, вызывающий функцию, должен теперь сам обработать ошибку. Конкретная реализация обработки ошибки будет зависеть от логики приложения. | 05.05.2008, 02:51 Ответить |
remitmasterdoronaltsophВ свое время решал эту задачу в более широком варианте. Основные плюсы моего решения: Более подробное описание, возможность поиграть с примерами и скачать код тут: | 24.02.2009, 13:43 Ответить |
04.05.2012, 23:01 Ответить |
rgbeastТакое преобразование всегда можно выполнить над результатом, используя функцию PHP ucfirst() | 05.05.2012, 13:10 Ответить |
Спасибо получилось, но столкнулся с очередной проблемой. При округлении числа, скрипт не работает, например: есть переменные $a=200; $b=3; $c=round($a/$b); при выводе переменной $c получим 67, но скрипт отказывается писать его прописью, хотя число целое. | 06.05.2012, 20:37 Ответить |
rgbeastround() возвращает не целое число, а float с нулями после запятой (см. http://ru.php.net/round ). Используйте intval ( round ( $a / $b ) ) ; | 06.05.2012, 21:13 Ответить |
1234ruС другой стороны, почему бы не модифицировать функцию так, чтобы она работала и с дробными числами? Следует отметить, что существительное в случае дробного числа всегда будет в единственном числе и родительном падеже (т.к. десятых/сотых/тысячных/и т.п. чего? секунды). rgbeastНаверное, имеет смысл написать дополнительную фунцию written_float(), которая будет использовать written_number() | 07.05.2012, 14:48 Ответить |
1234rurgbeastwritten_number() пока что очень простая функция. И, в основном, она нужна для целых чисел — в бухгалтерии пишут «Двадцать два рубля 00 коп» и никогда не превращают доли в текст. Функция для дробных будет очень сложной и, возможно, неоднозначной в зависимости от применения. Как, например, написать 3.1415926, 2.5e-19, 4.88e22, 0.333333333333333 или 0.999999999999999? Числа с плавающей точкой — отдельный мир, со своими правилами. Поэтому логично, что одни функцию для целых, другие — для float. | 07.05.2012, 16:26 Ответить |