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/.

Адрес уведомления об обратной ссылке для этой записи:

http://www.kraeg.ru/trackback/175