Вывести число прописью php

Вывести число прописью 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, 00:51
Ответить

rgbeast

А не лучше ли, в случае неверного типа входных данных, вместо die возвращать переданный аргумент? Мало ли, вдруг там число больше миллиона. Тогда правильней вернуть его, а не обрушивать весь скрипт. Ведь die довольно мощная функция. Она не только репортит ошибку, но и прекращает дальнейшую интерпритацию всего скрипта.

05.05.2008, 02:08
Ответить

rgbeast

die() в функции written_number() стояла скорее как маркер, чем как функциональная возможность, заменил die() на return false. Скрипт, вызывающий функцию, должен теперь сам обработать ошибку. Конкретная реализация обработки ошибки будет зависеть от логики приложения.

05.05.2008, 02:51
Ответить

remitmaster

doron

altsoph

В свое время решал эту задачу в более широком варианте.

Основные плюсы моего решения:
* реализация в виде отдельной библиотеки
* поддержка 6 русских падежей
* набор готовых перечислимых объектов (штуки, рубли, копейки, центы и т. п.) + возможность передать библиотеке произвольный перечислимый объект
* обработка и склонение десятичных дробей (до 6 знаков после запятой)

Более подробное описание, возможность поиграть с примерами и скачать код тут:
http://altsoph.ru/?p=522

24.02.2009, 13:43
Ответить

Отличный скрипт. Вопрос, можно ли сделать так, чтобы первое слово начиналось с заглавной буквы? Например, число 123, написать так:»Сто двадцать три»

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
Ответить

rgbeast

round() возвращает не целое число, а float с нулями после запятой (см. http://ru.php.net/round ). Используйте intval ( round ( $a / $b ) ) ;

06.05.2012, 21:13
Ответить

1234ru

С другой стороны, почему бы не модифицировать функцию так, чтобы она работала и с дробными числами?
Ведь говорят же, например «двадцать одна и девять десятых секунды» — т.е. надо брать intval(floor(число)).

Следует отметить, что существительное в случае дробного числа всегда будет в единственном числе и родительном падеже (т.к. десятых/сотых/тысячных/и т.п. чего? секунды).

rgbeast

Наверное, имеет смысл написать дополнительную фунцию written_float(), которая будет использовать written_number()

07.05.2012, 14:48
Ответить

1234ru

rgbeast

written_number() пока что очень простая функция. И, в основном, она нужна для целых чисел — в бухгалтерии пишут «Двадцать два рубля 00 коп» и никогда не превращают доли в текст. Функция для дробных будет очень сложной и, возможно, неоднозначной в зависимости от применения. Как, например, написать 3.1415926, 2.5e-19, 4.88e22, 0.333333333333333 или 0.999999999999999?

Числа с плавающей точкой — отдельный мир, со своими правилами. Поэтому логично, что одни функцию для целых, другие — для float.

07.05.2012, 16:26
Ответить

1234ru

1234ru

function get_digit ( $number , $digit ) <
# Получение разряда числа
$up = pow ( 10 , $digit ) ;
$down = pow ( 10 , $digit — 1 ) ;

return ( $number >= $down )
? floor ( ( $number % $up ) / $down )
: 0 ;
>

function number_written_alt ( $number , $words , $gender = ‘female’ ) <
# Возвращает число прописью в именительном падеже
# (используется для товарных чеков).
# $gender: female|male|middle

if ( ! is_array ( $words ) )
$words = explode ( ‘,’ , $words ) ;

$names = array (
1 => ‘тысяча,тысячи,тысяч’ ,
‘миллион,миллиона,миллионов’ ,
‘миллиард,миллиарда,миллиардов’ ,
// сюда добавить по желанию
) ;

foreach ( array_reverse ( $names , TRUE ) as $i => $w ) <

$pow = pow ( 1000 , $i ) ;

if ( $number >= $pow ) <
$str .= $F (
floor ( $number / $pow ) ,
$w ,
( ( $i == 1 ) ? ‘female’ : ‘male’ )
) . ‘ ‘ ;

if ( $number >= 100 ) <
$hundreds = array (
1 => ‘сто’ ,
‘двести’ ,
‘триста’ ,
‘четыреста’ ,
‘пятьсот’ ,
‘шестьсот’ ,
‘семьсот’ ,
‘восемьсот’ ,
‘девятьсот’
) ;
$h = get_digit ( $number , 3 ) ;
if ( isset ( $hundreds [ $h ] ) )
$str .= «$hundreds[$h] » ;
>

$d = get_digit ( $number , 2 ) ;

if ( $d >= 2 OR $d == 0 ) <
$decs = array (
2 => ‘двадцать’ ,
‘тридцать’ ,
‘сорок’ ,
‘пятьдесят’ ,
‘шестьдесят’ ,
‘семьдесят’ ,
‘восемьдесят’ ,
‘девяносто’
) ;
if ( isset ( $decs [ $d ] ) )
$str .= «$decs[$d] » ;

$u = get_digit ( $number , 1 ) ;

if ( $u > 2 ) <
$units = array (
3 => ‘три’ ,
‘четыре’ ,
‘пять’ ,
‘шесть’ ,
‘семь’ ,
‘восемь’ ,
‘девять’
) ;
$str .= «$units[$u] »
. (
( $u > 4 )
? $words [ 2 ]
: $words [ 1 ]
) ;
>

elseif ( $u == 2 ) <
$tmp = array (
‘female’ => ‘две’ ,
‘male’ => ‘два’ ,
‘middle’ => ‘два’
) ;
$str .= «$tmp[$gender] $words[1]» ;
>
elseif ( $u == 1 ) <
$tmp = array (
‘female’ => ‘одна’ ,
‘male’ => ‘один’ ,
‘middle’ => ‘одно’
) ;
$str .= «$tmp[$gender] $words[0]» ;
>
else
$str .= $words [ 2 ] ; // ноль

$sub_d = $number % 100 ;

$tmp = array (
10 => ‘десять’ ,
‘одиннадцать’ ,
‘двенадцать’ ,
‘тринадцать’ ,
‘четырнадцать’ ,
‘пятнадцать’ ,
‘шестнадцать’ ,
‘семнадцать’ ,
‘восемьнадцать’ ,
‘девятнадцать’
) ;
$str .= «$tmp[$sub_d] $words[2]» ;
unset ( $tmp ) ;
>

Источник

Читайте также:  Чем вывести солярку с джинс
Оцените статью