65

Is there a function that will express any given number in words?

For example:

If a number is 1432, then this function will return "One thousand four hundred and thirty two".

Rotimi
  • 4,710
  • 4
  • 17
  • 27
anita.kcx
  • 863
  • 2
  • 11
  • 18

3 Answers3

165

Use the NumberFormatter class that are in php ;)

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

That would output "one thousand four hundred thirty-two"

martindilling
  • 2,649
  • 3
  • 15
  • 13
  • 2
    It's part of the PECL intl extension – yitznewton Dec 28 '14 at 03:12
  • 15
    If you want a more verbose output use `$f->setTextAttribute(NumberFormatter::DEFAULT_RULESET, "%spellout-numbering-verbose");` which will output `one thousand four hundred and thirty-two` – Chris Wheeler Dec 31 '15 at 15:35
  • How does one get the PECL intl extension? Ubuntu PHP 7.2 server. Also is this still OK? It's maintenance stopped in 2013 with version 3.0.0 @yitznewton – s3c May 06 '20 at 11:17
  • Sorry, I switched companies and stopped using PHP right after I posted that comment, so I'm afraid I don't know anything about the current ecosystem – yitznewton May 27 '21 at 10:35
  • This "$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);" is not working for me, any tips to make this work? I'm using MS Edge for this. – MJ Delos Santos Oct 25 '21 at 01:19
42

You can do this in many ways I am mentioning here two ways by using The NumberFormatter class as mentioned in Martindilling answer (if you have php version 5.3.0 or higher and also PECL extension 1.0.0 or higher) or by using the following custom function.

function convertNumberToWord($num = false)
{
    $num = str_replace(array(',', ' '), '' , trim($num));
    if(! $num) {
        return false;
    }
    $num = (int) $num;
    $words = array();
    $list1 = array('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
        'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
    );
    $list2 = array('', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety', 'hundred');
    $list3 = array('', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion',
        'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
        'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion', 'vigintillion'
    );
    $num_length = strlen($num);
    $levels = (int) (($num_length + 2) / 3);
    $max_length = $levels * 3;
    $num = substr('00' . $num, -$max_length);
    $num_levels = str_split($num, 3);
    for ($i = 0; $i < count($num_levels); $i++) {
        $levels--;
        $hundreds = (int) ($num_levels[$i] / 100);
        $hundreds = ($hundreds ? ' ' . $list1[$hundreds] . ' hundred' . ' ' : '');
        $tens = (int) ($num_levels[$i] % 100);
        $singles = '';
        if ( $tens < 20 ) {
            $tens = ($tens ? ' ' . $list1[$tens] . ' ' : '' );
        } else {
            $tens = (int)($tens / 10);
            $tens = ' ' . $list2[$tens] . ' ';
            $singles = (int) ($num_levels[$i] % 10);
            $singles = ' ' . $list1[$singles] . ' ';
        }
        $words[] = $hundreds . $tens . $singles . ( ( $levels && ( int ) ( $num_levels[$i] ) ) ? ' ' . $list3[$levels] . ' ' : '' );
    } //end for loop
    $commas = count($words);
    if ($commas > 1) {
        $commas = $commas - 1;
    }
    return implode(' ', $words);
}
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
Shahbaz
  • 3,323
  • 1
  • 25
  • 41
  • 3
    Nice function, looks ok so far - note that `hundred` is always `hundred` and will not follow with an `s` – Onimusha Nov 07 '15 at 01:33
  • If it helps you you should vote up, but If you vote down please explain the reason! Thanks – Shahbaz Mar 02 '16 at 12:59
  • Nice function. But I think you should fix the "hundreds" thing. @Onimusha has also pointed this out. – Stephen Adelakun May 24 '17 at 19:32
  • thanks @StephenAdelakun for reminder but its just a variable the actual string used is hundred. – Shahbaz May 25 '17 at 05:16
  • it doesn't show the point part ..How do you concat that? – Hola Jun 15 '17 at 05:02
  • `return implode(' ', $words);` gave me a bunch of weird white space between and around words. This won't be noticeable if the strings are output to html of course, but for the OCD crowd you can use a regex and trim() to eliminate it. Replace that line with `return trim(preg_replace('~[\\s]+~', ' ', implode(' ', $words)));` – sfscs Nov 16 '19 at 04:04
  • When dealing large numbers larger dan int, use floor. `$num = floor($num);`. Wrong output when number is larger than 2billion – reignsly May 19 '20 at 11:22
9

In case of using Yii2 you can do this as simple as the following:

$sum = 100500;
echo Yii::$app->formatter->asSpellout($sum);

This prints spelled out $sum in your app's language.

Docs reference

Alliswell
  • 1,425
  • 19
  • 34