Search code examples
phppreg-replacepreg-matchpreg-match-allnumber-formatting

How to replace number described by words back into number?


I'm setting up a program that read's a user's input message and breaks down the response by words.

In order for it to adapt, I would need to transform numbers described by a string such as one million, 35 million, 230 thousand, back into 1000000,35000000,20000.

I've tried a few ways but can't find one that works.

For example user posts one million:

 <?php
$string=mysql_escape_string($_POST['message'];
// Do something to the string to transform one million into 1000000
return number 
?>

Solution

  • Check Converting words to numbers in PHP:

    /**
     * Convert a string such as "one hundred thousand" to 100000.00.
     *
     * @param string $data The numeric string.
     *
     * @return float or false on error
     */
    function wordsToNumber($data) {
        // Replace all number words with an equivalent numeric value
        $data = strtr(
            $data,
            array(
                'zero'      => '0',
                'a'         => '1',
                'one'       => '1',
                'two'       => '2',
                'three'     => '3',
                'four'      => '4',
                'five'      => '5',
                'six'       => '6',
                'seven'     => '7',
                'eight'     => '8',
                'nine'      => '9',
                'ten'       => '10',
                'eleven'    => '11',
                'twelve'    => '12',
                'thirteen'  => '13',
                'fourteen'  => '14',
                'fifteen'   => '15',
                'sixteen'   => '16',
                'seventeen' => '17',
                'eighteen'  => '18',
                'nineteen'  => '19',
                'twenty'    => '20',
                'thirty'    => '30',
                'forty'     => '40',
                'fourty'    => '40', // common misspelling
                'fifty'     => '50',
                'sixty'     => '60',
                'seventy'   => '70',
                'eighty'    => '80',
                'ninety'    => '90',
                'hundred'   => '100',
                'thousand'  => '1000',
                'million'   => '1000000',
                'billion'   => '1000000000',
                'and'       => '',
            )
        );
    
        // Coerce all tokens to numbers
        $parts = array_map(
            function ($val) {
                return floatval($val);
            },
            preg_split('/[\s-]+/', $data)
        );
    
        $stack = new SplStack; // Current work stack
        $sum   = 0; // Running total
        $last  = null;
    
        foreach ($parts as $part) {
            if (!$stack->isEmpty()) {
                // We're part way through a phrase
                if ($stack->top() > $part) {
                    // Decreasing step, e.g. from hundreds to ones
                    if ($last >= 1000) {
                        // If we drop from more than 1000 then we've finished the phrase
                        $sum += $stack->pop();
                        // This is the first element of a new phrase
                        $stack->push($part);
                    } else {
                        // Drop down from less than 1000, just addition
                        // e.g. "seventy one" -> "70 1" -> "70 + 1"
                        $stack->push($stack->pop() + $part);
                    }
                } else {
                    // Increasing step, e.g ones to hundreds
                    $stack->push($stack->pop() * $part);
                }
            } else {
                // This is the first element of a new phrase
                $stack->push($part);
            }
    
            // Store the last processed part
            $last = $part;
        }
    
        return $sum + $stack->pop();
    }