Is there an easy way to convert a number to a word in PHP?

Viewed 67108

In PHP, is there an easy way to convert a number to a word? For instance, 27 to twenty-seven.

14 Answers

I found some (2007/2008) source-code online and as it is copyright but I can use it freely and modify it however I want, so I place it here and re-license under CC-Wiki:

<?php
/**
 * English Number Converter - Collection of PHP functions to convert a number
 *                            into English text.
 *
 * This exact code is licensed under CC-Wiki on Stackoverflow.
 * http://creativecommons.org/licenses/by-sa/3.0/
 *
 * @link     http://stackoverflow.com/q/277569/367456
 * @question Is there an easy way to convert a number to a word in PHP?
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *   Copyright 2007-2008 Brenton Fletcher. http://bloople.net/num2text
 *   You can use this freely and modify it however you want.
 */

function convertNumber($number)
{
    list($integer, $fraction) = explode(".", (string) $number);

    $output = "";

    if ($integer{0} == "-")
    {
        $output = "negative ";
        $integer    = ltrim($integer, "-");
    }
    else if ($integer{0} == "+")
    {
        $output = "positive ";
        $integer    = ltrim($integer, "+");
    }

    if ($integer{0} == "0")
    {
        $output .= "zero";
    }
    else
    {
        $integer = str_pad($integer, 36, "0", STR_PAD_LEFT);
        $group   = rtrim(chunk_split($integer, 3, " "), " ");
        $groups  = explode(" ", $group);

        $groups2 = array();
        foreach ($groups as $g)
        {
            $groups2[] = convertThreeDigit($g{0}, $g{1}, $g{2});
        }

        for ($z = 0; $z < count($groups2); $z++)
        {
            if ($groups2[$z] != "")
            {
                $output .= $groups2[$z] . convertGroup(11 - $z) . (
                        $z < 11
                        && !array_search('', array_slice($groups2, $z + 1, -1))
                        && $groups2[11] != ''
                        && $groups[11]{0} == '0'
                            ? " and "
                            : ", "
                    );
            }
        }

        $output = rtrim($output, ", ");
    }

    if ($fraction > 0)
    {
        $output .= " point";
        for ($i = 0; $i < strlen($fraction); $i++)
        {
            $output .= " " . convertDigit($fraction{$i});
        }
    }

    return $output;
}

function convertGroup($index)
{
    switch ($index)
    {
        case 11:
            return " decillion";
        case 10:
            return " nonillion";
        case 9:
            return " octillion";
        case 8:
            return " septillion";
        case 7:
            return " sextillion";
        case 6:
            return " quintrillion";
        case 5:
            return " quadrillion";
        case 4:
            return " trillion";
        case 3:
            return " billion";
        case 2:
            return " million";
        case 1:
            return " thousand";
        case 0:
            return "";
    }
}

function convertThreeDigit($digit1, $digit2, $digit3)
{
    $buffer = "";

    if ($digit1 == "0" && $digit2 == "0" && $digit3 == "0")
    {
        return "";
    }

    if ($digit1 != "0")
    {
        $buffer .= convertDigit($digit1) . " hundred";
        if ($digit2 != "0" || $digit3 != "0")
        {
            $buffer .= " and ";
        }
    }

    if ($digit2 != "0")
    {
        $buffer .= convertTwoDigit($digit2, $digit3);
    }
    else if ($digit3 != "0")
    {
        $buffer .= convertDigit($digit3);
    }

    return $buffer;
}

function convertTwoDigit($digit1, $digit2)
{
    if ($digit2 == "0")
    {
        switch ($digit1)
        {
            case "1":
                return "ten";
            case "2":
                return "twenty";
            case "3":
                return "thirty";
            case "4":
                return "forty";
            case "5":
                return "fifty";
            case "6":
                return "sixty";
            case "7":
                return "seventy";
            case "8":
                return "eighty";
            case "9":
                return "ninety";
        }
    } else if ($digit1 == "1")
    {
        switch ($digit2)
        {
            case "1":
                return "eleven";
            case "2":
                return "twelve";
            case "3":
                return "thirteen";
            case "4":
                return "fourteen";
            case "5":
                return "fifteen";
            case "6":
                return "sixteen";
            case "7":
                return "seventeen";
            case "8":
                return "eighteen";
            case "9":
                return "nineteen";
        }
    } else
    {
        $temp = convertDigit($digit2);
        switch ($digit1)
        {
            case "2":
                return "twenty-$temp";
            case "3":
                return "thirty-$temp";
            case "4":
                return "forty-$temp";
            case "5":
                return "fifty-$temp";
            case "6":
                return "sixty-$temp";
            case "7":
                return "seventy-$temp";
            case "8":
                return "eighty-$temp";
            case "9":
                return "ninety-$temp";
        }
    }
}

function convertDigit($digit)
{
    switch ($digit)
    {
        case "0":
            return "zero";
        case "1":
            return "one";
        case "2":
            return "two";
        case "3":
            return "three";
        case "4":
            return "four";
        case "5":
            return "five";
        case "6":
            return "six";
        case "7":
            return "seven";
        case "8":
            return "eight";
        case "9":
            return "nine";
    }
}

Alternatively, you can use the NumberFormatter class from intl package in PHP . Here's a sample code to get you started (for commandline):

<?php
if ($argc < 3) 
    {
    echo "usage: php {$argv[0]} lang-tag number ...\n";
    exit;
    }

array_shift($argv);
$lang_tag = array_shift($argv);

$nf1 = new NumberFormatter($lang_tag, NumberFormatter::DECIMAL);
$nf2 = new NumberFormatter($lang_tag, NumberFormatter::SPELLOUT);

foreach ($argv as $num) 
    {
    echo $nf1->format($num).' is '.$nf2->format($num)."\n"; 
    }

There is the Numbers_Words package in PECL. It does exactly what you ask for. The following languages are supported:

  • bg (Bulgarian) by Kouber Saparev
  • cs (Czech) by Petr 'PePa' Pavel
  • de (German) by Piotr Klaban
  • dk (Danish) by Jesper Veggerby
  • en_100 (Donald Knuth system, English) by Piotr Klaban
  • en_GB (British English) by Piotr Klaban
  • en_US (American English) by Piotr Klaban
  • es (Spanish Castellano) by Xavier Noguer
  • es_AR (Argentinian Spanish) by Martin Marrese
  • et (Estonian) by Erkki Saarniit
  • fr (French) by Kouber Saparev
  • fr_BE (French Belgium) by Kouber Saparev and Philippe Bajoit
  • he (Hebrew) by Hadar Porat
  • hu_HU (Hungarian) by Nils Homp
  • id (Indonesian) by Ernas M. Jamil and Arif Rifai Dwiyanto
  • it_IT (Italian) by Filippo Beltramini and Davide Caironi
  • lt (Lithuanian) by Laurynas Butkus
  • nl (Dutch) by WHAM van Dinter
  • pl (Polish) by Piotr Klaban
  • pt_BR (Brazilian Portuguese) by Marcelo Subtil Marcal and Mario H.C.T.
  • ru (Russian) by Andrey Demenev
  • sv (Swedish) by Robin Ericsson

You can use the NumberFormatter Class:

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

Yes there is. without using a library you just need to follow this..

First you need to check in your server if ;extension=php_intl.dll is enabled in your php.ini if still not work you need to see this answer.

intl extension php_intl.dll with wamp

after successfully moving all the files starts with icu.

from: <wamp_installation_path>/bin/php/php5.4.3/

to: <wamp_installation_path>/bin/apache/apache2.2.22/bin/

and restart your server.

try to run this code:

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

it will show the output of one hundred twenty-three thousand four hundred fifty-six.

hope that helps everyone :).

<?php
$grandTotalAmount = 700000000;
echo ($grandTotalAmount == round($grandTotalAmount)) ? convert_number_to_words(floatval($grandTotalAmount)) . ' Only' : convert_number_to_words(floatval($grandTotalAmount)) . ' Only';

function convert_number_to_words($number) {
    $hyphen = ' ';
    $conjunction = ' and ';
    $separator = ', ';
    $negative = 'negative ';
    $decimal = ' Thai Baht And ';
    $dictionary = array(
        0 => 'zero',
        1 => 'one',
        2 => 'two',
        3 => 'three',
        4 => 'four',
        5 => 'five',
        6 => 'six',
        7 => 'seven',
        8 => 'eight',
        9 => 'nine',
        10 => 'ten',
        11 => 'eleven',
        12 => 'twelve',
        13 => 'thirteen',
        14 => 'fourteen',
        15 => 'fifteen',
        16 => 'sixteen',
        17 => 'seventeen',
        18 => 'eighteen',
        19 => 'nineteen',
        20 => 'twenty',
        30 => 'thirty',
        40 => 'fourty',
        50 => 'fifty',
        60 => 'sixty',
        70 => 'seventy',
        80 => 'eighty',
        90 => 'ninety',
        100 => 'hundred',
        1000 => 'thousand',
        1000000 => 'million',
        1000000000 => 'billion',
        1000000000000 => 'trillion',
        1000000000000000 => 'quadrillion',
        1000000000000000000 => 'quintillion'
    );

    if (!is_numeric($number)) {
        return false;
    }

    if (($number >= 0 && (int) $number < 0) || (int) $number < 0 - PHP_INT_MAX) {
        // overflow
        trigger_error(
                'convert_number_to_words only accepts numbers between -' . PHP_INT_MAX . ' and ' . PHP_INT_MAX, E_USER_WARNING
        );
        return false;
    }

    if ($number < 0) {
        return $negative . convert_number_to_words(abs($number));
    }

    $string = $fraction = null;


    if (strpos($number, '.') !== false) {
        list($number, $fraction) = explode('.', $number);
    }

    switch (true) {
        case $number < 21:
            $string = $dictionary[$number];
            break;
        case $number < 100:
            $tens = ((int) ($number / 10)) * 10;
            $units = $number % 10;
            $string = $dictionary[$tens];
            if ($units) {
                $string .= $hyphen . $dictionary[$units];
            }
            break;
        case $number < 1000:
            $hundreds = $number / 100;
            $remainder = $number % 100;
            $string = $dictionary[$hundreds] . ' ' . $dictionary[100];
            if ($remainder) {
                $string .= $conjunction . convert_number_to_words($remainder);
            }
            break;
        default:
            $baseUnit = pow(1000, floor(log($number, 1000)));
            $numBaseUnits = (int) ($number / $baseUnit);
            $remainder = $number % $baseUnit;
            $string = convert_number_to_words($numBaseUnits) . ' ' . $dictionary[$baseUnit];
            if ($remainder) {
                $string .= $remainder < 100 ? $conjunction : $separator;
                $string .= convert_number_to_words($remainder);
            }
            break;
    }

    if (null !== $fraction && is_numeric($fraction)) {
        $string .= $decimal;
        $words = array();
        foreach (str_split((string) $fraction) as $number) {
            $words[] = $dictionary[$number];
        }
        $string .= implode(' ', $words);
    }

    return $string;
}
?>

The below code is working fine

$test = 1000025.05;

$f = new \NumberFormatter( locale_get_default(), \NumberFormatter::SPELLOUT );

$word = $f->format($test);

echo $word;
protected function numberTextHelper($number)
{
    if (($number < 0) || ($number > 999999999)) 
    {
        throw new Exception("Number is out of range");
    }
    
    $ones = array("", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eightteen", "Nineteen");
    $tens = array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eigthy", "Ninety");
    
    $giga = floor($number / 1000000);
    // Millions (giga)
    $number -= $giga * 1000000;

    $thousands = floor($number / 1000);
    
    // Thousands (kilo)
    $number -= $thousands * 1000;
    
    $hecto = floor($number / 100);
    
    // Hundreds (hecto)
    $number -= $hecto * 100;
    
    $deca = floor($number / 10);
    
    // Tens (deca)
    $n = $number % 10;
    
    $frac  = round($number - (int)$number,2); 

    // Ones
    $result = array();
    if ($giga) 
    {
        $result[]= $this->numberTextHelper($giga).' '.($giga>1?'MILLIONS':'MILLION');
    }
    
    if ($thousands) 
    {
        $result[]= $thousands>1?$this->numberTextHelper($thousands).' THOUSANDS':'THOUSAND';
    }
    
    if ($hecto) 
    {
        $result[]= $this->numberTextHelper($hecto).'HUNDRED';
    }
    
    if ($deca) 
    {
        if($deca<2)
        {
            $result[]= $ones[$deca * 10 + $n];
            $n=0;
        }
        else
        {
            $result[]= $tens[$deca];
        }
    }
            

    if ($n) 
    {
        $result[]= $ones[$n];
    }

    if($frac) 
    {
        $result[]= 'and';
        $result[]= $this->numberTextHelper($frac*100);
        $result[]= 'cents';
    }
    
    if(empty($result)) 
    {
        $result[]= 'zero';
    }
    
    return implode(' ',$result);
}   

And you can translate it

function numberText($number)
{
    $result=$this->numberTextHelper($number);
    $result=$this->strtoupper($result);
    $text=array_filter(explode(' ',$result));
    $translated=array_map(array($this,'getLang'),$text);
    return implode(' ',$translated);
}
Related