0

I have some code that converts a number, that contains two decimal places, to words.

However, there's something wrong with the current code. It adds an additional thousand to the each and every number, so this code wrongly converts e.g. 15,000.00 to 15 million

I have tried changing the figures.

function smarty_modifier_no2words($number, $uk = 0) {
    if (!is_string($number)) $number.= "";
    if (!$uk) $many = array('', ' thousand ', ' million ', ' billion ', ' trillion');
    else $many = array('', ' thousand ', ' million ', ' milliard ', ' billion ');
    $string = '';
    if (strlen($number) % 3 != 0) {
        $string.= smarty_modifier_no2words_hunderds(substr($number, 0, strlen($number) % 3));
        $string.= $many[floor(strlen($number) / 3) ];
        for ($i = 0;$i < floor(strlen($number) / 3);$i++) {
            $string.= smarty_modifier_no2words_hunderds(substr($number, strlen($number) % 3 + ($i * 3), 3));
            if ($number[strlen($number) % 3 + ($i * 3) ] != 0) $string.= $many[floor(strlen($number) / 3) - 1 - $i];
        }
        return $string;
    }
    function smarty_modifier_no2words_hunderds($number) {
        $test = $number * 1;
        if (empty($test)) return;
        $lasts = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
        $teens = array('eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
        $teen = array('ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety');
        $string = '';
        $j = strlen($number);
        $done = false;
        for ($i = 0;$i < strlen($number);$i++) {
            if ($j == 2) {
                if (strlen($number) > 2) {
                    if ($number[0] != 0) $string.= ' hundred ';
                    if (substr($number, $i + 1)) $string.= 'and ';
                }
                if ($number[$i] == 1) {
                    if ($number[$i + 1] == 0) $string.= $teen[$number[$i] - 1];
                    else {
                        $string.= $teens[$number[$i + 1] - 1];
                        $done = true;
                    }
                } else {
                    if (!empty($teen[$number[$i] - 1])) $string.= $teen[$number[$i] - 1] . ' ';
                }
            } elseif ($number[$i] != 0 && !$done) $string.= $lasts[$number[$i] - 1];
            $j--;
        }
        return $string;
    }
?>

How can I fix it?

N69S
  • 16,110
  • 3
  • 22
  • 36
HRAC
  • 1
  • 1

1 Answers1

1

You could simplify your problem statement as "How do I convert the string '15,000.00' to a number?", the quick and dirty answer to which is:

(float)preg_replace('/[^\d\-\.]/', '', $input);

Though the full-fledged solution that deals with most of the edge cases that would otherwise cause problems is much longer.

But you've shown a secondary problem where you're using string functions to deal with numbers, which is always a huge red flag to me. Use math:

$input = 15000.00;
$magnitudes = ['', 'thousand', 'million', 'billion'];
$magnitude = (int)(log($input, 10) / 3);
$factor = $input/pow(10,$magnitude*3);

var_dump(sprintf("%d %s", $factor, $magnitudes[$magnitude]));

Output:

string(11) "15 thousand"

And even still this problem is pre-solved:

$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
var_dump($f->format(123456789));

Output:

string(90) "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine"
Sammitch
  • 30,782
  • 7
  • 50
  • 77