Изписване на числа

dakata__92

Super Moderator
Здравейте колеги. Имам проблем, който не успявам да измъдря, как точно да реша. Ако на този метод подам 132 000 вместо да ми върне „сто тридесет и две хиляди“ ми връща „сто тридесет и два хиляди“. Това се решава в казуса след коментара „/* До милион */“.
Тест:
Код:
$number = 132000;
echo $this->bg($number);

Код:
Код:
    public function bg($integer, $fraction = false): string
    {
        $integer = (int)$integer;
        if ($integer >= 2000000000) {
            return false;
        }

        $num0 = [
            0 => "нула",
            1 => "един",
            2 => "две",
            3 => "три",
            4 => "четири",
            5 => "пет",
            6 => "шест",
            7 => "седем",
            8 => "осем",
            9 => "девет",
            10 => "десет",
            11 => "единадесет",
            12 => "дванадесет"
        ];

        $num100 = [
            1 => "сто",
            2 => "двеста",
            3 => "триста"
        ];

        $_div10 = ($integer - $integer % 10) / 10;
        $_mod10 = $integer % 10;
        $_div100 = ($integer - $integer % 100) / 100;
        $_mod100 = $integer % 100;
        $_div1000 = ($integer - $integer % 1000) / 1000;
        $_mod1000 = $integer % 1000;
        $_div1000000 = ($integer - $integer % 1000000) / 1000000;
        $_mod1000000 = $integer % 1000000;
        $_div1000000000 = ($integer - $integer % 1000000000) / 1000000000;
        $_mod1000000000 = $integer % 1000000000;

        if ($integer == 0) {
            return $num0[$integer];
        }
        if ($integer < 0) {
            return 'минус ' . $this->bg(abs($integer));
        }
        if ($integer > 0 && $integer < 20) {
            if ($fraction && $integer == 1)
                return "една";
            if ($fraction && $integer == 2)
                return "две";
            if ($integer == 2)
                return "два";
            return isset($num0[$integer]) ? $num0[$integer] : $num0[$_mod10] . "надесет";
        }

        if ($integer > 19 && $integer < 100) {
            $tmp = ($_div10 == 2) ? "двадесет" : $num0[$_div10] . "десет";
            $tmp = $_mod10 ? $tmp . " и " . $this->bg($_mod10, $fraction) : $tmp;
            return $tmp;
        }
        /* До хиляда */
        if ($integer > 99 && $integer < 1000) {
            $tmp = isset($num100[$_div100]) ? $num100[$_div100] : $num0[$_div100] . "стотин";
            if (($_mod100 % 10 == 0 || $_mod100 < 20) && $_mod100 != 0) {
                $tmp .= " и";
            }
            if ($_mod100) {
                $tmp .= " " . $this->bg($_mod100);
            }
            return $tmp;
        }

        /* До милион */
        if ($integer > 999 && $integer < 1000000) {
            /* Damn bulgarian @#$%@#$% два хиляди is wrong :) */
            $tmp = ($_div1000 == 1) ? "хиляда" :
                (($_div1000 == 2) ? "две хиляди" : $this->bg($_div1000) . " хиляди");
            $num0[2] = "два";
            if (($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0) {
                if (!(($_mod100 % 10 == 0 || $_mod100 < 20) && $_mod100 != 0)) {
                    $tmp .= " и";
                }
            }
            if (($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0 && $_mod1000 < 100) {
                $tmp .= " и";
            }
            if ($_mod1000) {
                $tmp .= " " . $this->bg($_mod1000);
            }
            return $tmp;
        }

        /* Над милион */
        if ($integer > 999999 && $integer < 1000000000) {
            $tmp = ($_div1000000 == 1) ? "един милион" : $this->bg($_div1000000) . " милиона";
            if (($_mod1000000 % 10 == 0 || $_mod1000000 < 20) && $_mod1000000 != 0) {
                if (!(($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0)) {
                    if (!(($_mod100 % 10 == 0 || $_mod100 < 20) && $_mod100 != 0)) {
                        $tmp .= " и";
                    }
                }
            }
            if (($_mod1000000 % 10 == 0 || $_mod1000000 < 20) && $_mod1000000 != 0 && $_mod1000000 < 1000) {
                if (($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0 && $_mod1000 < 100) {
                    $tmp .= " и";
                }
            }
            if ($_mod1000000) {
                $tmp .= " " . $this->bg($_mod1000000);
            }
            return $tmp;
        }
        /* Над милиард */
        if ($integer > 99999999 && $integer <= 2000000000) {
            $tmp = ($_div1000000000 == 1) ? "един милиард" : "";
            $tmp = ($_div1000000000 == 2) ? "два милиарда" : $tmp;
            if ($_mod1000000000) {
                $tmp .= " " . $this->bg($_mod1000000000);
            }
            return $tmp;
        }
        return false;
    }
 
/* До хиляда */
if ($integer > 99 && $integer < 1000) {
$tmp = isset($num100[$_div100]) ? $num100[$_div100] : $num0[$_div100] . "стотин";
if (($_mod100 % 10 == 0 || $_mod100 < 20) && $_mod100 != 0) {
$tmp .= " и";
}
if ($_mod100) {
$tmp .= " " . $this->bg($_mod100, $fraction);
}
return $tmp;
}

/* До милион */
if ($integer > 999 && $integer < 1000000) {
/* Damn bulgarian @#$%@#$% два хиляди is wrong :) */
$tmp = ($_div1000 == 1) ? "хиляда" :
(($_div1000 == 2) ? "две хиляди" : $this->bg($_div1000, true) . " хиляди");
$num0[2] = "два";
if (($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0) {
if (!(($_mod100 % 10 == 0 || $_mod100 < 20) && $_mod100 != 0)) {
$tmp .= " и";
}
}
if (($_mod1000 % 10 == 0 || $_mod1000 < 20) && $_mod1000 != 0 && $_mod1000 < 100) {
$tmp .= " и";
}
if ($_mod1000) {
$tmp .= " " . $this->bg($_mod1000);
}
return $tmp;
}

Трябва да добавиш fraction = true когато имаш десетки или стотици хиляди.
 
Ами функцията се извиква рекурсивно. $fraction де факто е втория параметър на функцията. В този случай, само когато имаш хилядни, които са в десетки или стотици, ти трябва тази фракция (според кода, ако погледнеш по-нагоре ще видиш, че "две" се образува когато фракцията е истина).

Другия вариант ти е да подадеш на двете места тази променлива и да извикаш после

Код:
$this->bg(132000, true);

но така въпреки, че ще даде верен резултат отново не съм сигурен дали това ще е вярно във всеки случай.
 
Revelation каза:
Ами функцията се извиква рекурсивно. $fraction де факто е втория параметър на функцията. В този случай, само когато имаш хилядни, които са в десетки или стотици, ти трябва тази фракция (според кода, ако погледнеш по-нагоре ще видиш, че "две" се образува когато фракцията е истина).

Другия вариант ти е да подадеш на двете места тази променлива и да извикаш после

Код:
$this->bg(132000, true);

но така въпреки, че ще даде верен резултат отново не съм сигурен дали това ще е вярно във всеки случай.
За сега е супер и няма проблем. Благодаря +1 по темата!
 
А каква е причината да не се ползват готовите решения? Смисъл кой да го еба си е играл да го пише това цялото след като има вече библиотеки за това?
 
uphero каза:
А каква е причината да не се ползват готовите решения? Смисъл кой да го еба си е играл да го пише това цялото след като има вече библиотеки за това?

За мен решението е готово, не е писано от мен. Прати някоя библиотека да я разгледам, не ми пречи.
 

Горе