PHP функция, для получения суммы прописью

Знаю что эта тема уже поднималась, но предложенный вариант, также как и функция которой я пользовался до этого, оставляли чувство что задачу можно решить проще и элегантнее. Поэтому я сел, проанализировал задачу и написал еще один велосипед вариант. В результате у меня получилось две функции. В класс я их не стал заворачивать, чтобы они пригодились и тем кто сидит на php4 и те кто на php5.

Вы спросите — зачем? я пытался добиться простоты и прозрачности реализации. В итоге, как мне показалось, у меня получилось достаточно простая структура
— подготовка массивов с данными
— нормализация входного значения
— обработка этого значения

Пример использования:

num2str(878867.15);

выведет:

восемьсот семьдесят восемь тысяч восемьсот шестьдесят семь рублей пятнадцать копеек

Далее сам код…

function num2str($inn=0) {
$o = array(); // Результаты
$str= array(); // Основные массивы с строками
$str[0] = array('','сто','двести','триста','четыреста','пятьсот','шестьсот','семьсот', 'восемьсот','девятьсот','тысяча');
$str[1] = array('','десять','двадцать','тридцать','сорок','пятьдесят','шестьдесят', 'семьдесят','восемьдесят','девяносто','сто');
// названия чисел для сущностей женского рода
$str[2] = array('','один','два','три','четыре','пять','шесть', 'семь','восемь','девять','десять');
// названия чисел для сущностей мужского рода
$str[3] = array('','одна','две','три','четыре','пять','шесть', 'семь','восемь','девять','десять');
$str11 = array(11=>'одиннадцать',12=>'двенадцать',13=>'тринадцать',14=>'четырнадцать',
15=>'пятнадцать',16=>'шестнадцать',17=>'семнадцать', 18=>'восемнадцать',19=>'девятнадцать',20=>'двадцать');
$forms = array(
// 1 2,3,4 5... род слова(индекс для $str )
array('копейка', 'копейки', 'копеек', 3),
array('рубль', 'рубля', 'рублей', 2), // 10^0
array('тысяча', 'тысячи', 'тысяч', 3), // 10^3
array('миллион', 'миллиона', 'миллионов', 2), // 10^6
array('миллиард','миллиарда','миллиардов',2), // 10^9
array('триллион','триллиона','триллионов',2), // 10^12
// можно дописать всякие секстилионы ...
);

// Нормализация значения, избавляемся от ТОЧКИ, например 6754321.67 переводим в 7654321067
$tmp = explode('.', str_replace(',','.', $inn));
$rub = $tmp[0]; // рубли
$kop = isset($tmp[1]) ? str_pad(str_pad($tmp[1], 2, '0'), 3, '0',STR_PAD_LEFT) : '000'; // копейки
$rub .= $kop; // нормализованное значение

// Поехали!
$levels = explode('-', number_format($rub,0,'','-') );
$offset = sizeof($levels)-1;
foreach($levels as $k=>$level) {
$index = $offset-$k;
$level = str_pad($level, 3, '0', STR_PAD_LEFT);
if (!empty($str[0][$level[0]])) $o[] = $str[0][$level[0]];
$tmp = intval($level[1].$level[2]);
if ($tmp>20) {
$tmp = strval($tmp);
for($i=0,$m=strlen($tmp); $i<$m; $i++) {
// $forms[$index][3] - род слова для текущего уровня
$rod = $forms[$index][3];
$tmp_o = ($i+1)==2 ? $str[$rod][$tmp[$i]] : $str[$i+1][$tmp[$i]];
if (!empty($tmp_o)) $o[]= $tmp_o;
}
}
else {
$o[] = ($tmp>10 ? $str11[$tmp] : $str[$forms[$index][3]][$tmp] );
}
$tmp_o = pluralForm($level, $forms[$index][0], $forms[$index][1] ,$forms[$index][2] );
if (!empty($tmp_o)) $o[] = $tmp_o;
}
if ('000'==$kop) { // Если ноль копеек
$o[] = '00';
$o[] = $forms[0][2];
}
return implode(' ',$o);
}

function pluralForm($n, $f1, $f2, $f5) {
if (intval($n)==0)
return '';
$n = abs($n) % 100;
$n1 = $n % 10;
if ($n > 10 && $n < 20) return $f5;
if ($n1 > 1 && $n1 < 5) return $f2;
if ($n1 == 1) return $f1;
return $f5;
}

http://habrahabr.ru/blogs/php/53210/

7 комментариев

  1. Спасибо. ) хорошая функция, только нужна небольшая доработка:
    1) сделать выбор выводить копейки либо цифрами, либо словами
    3) с копейками может быть косяк, если после точки оказалось больше двух цифр, например
    echo num2str(12.3456789);
    выведет: сто двадцать три тысячи четыреста пятьдесят шесть рублей семьсот восемьдесят девять копеек

Оставить комментарий

Ваш электронный адрес не будет опубликован.


*


16 + 16 =