Developer

Converting numbers to words in PHP

If you ever have to create a PHP application built around invoicing or accounting, you might find the PHP PEAR Numbers_Words class useful. Its sole reason for existence is to help you translate integers into their spoken-word equivalents.


Every once in a while, the PHP PEAR repository throws up a gem. This one's for anyone who's ever had to create a PHP application built around invoicing or accounting—it's called the PHP PEAR Numbers_Words class and its sole reason for existence is to help you translate integers into their spoken equivalents.

Use both words and numbers to avoid confusion
How is this useful? Well, consider the typical invoice: In addition to a description of the work done, the date, and the hourly or project cost, it always includes a total cost at the end—the amount that the customer is expected to pay. To avoid any misinterpretation of the total amount, many organizations (mine included) put the amount in both words and figures; for example, $1,200 becomes "one thousand and two hundred dollars." You probably do the same thing every time you write a check.

Now take this scenario to a Web-based invoicing system. The actual data used to generate the invoice will be stored in a database as integers, both to save space and to simplify calculations. So when a printable invoice is generated, your Web application will need to convert those integers into words.

This is a trivial problem...or so I thought. I had to perform precisely this task for an application I was putting together, and it turns out it wasn't anywhere near as easy as it sounds. You try writing a generic routine to convert the numbers 1200000, 12000 and 120 into words, and you'll see just how difficult it is. However, it's a common problem, and that's why the PEAR Numbers_Words class was created—it provides a simple, efficient solution to the problem.

Simple stuff
I'll assume that you have a working PHP/Apache installation with the default PEAR files installed and all paths correctly set up. To begin, download the class from http://pear.php.net/package-info.php?package=Numbers_Words and install it to your PEAR directory. Next, create the following simple PHP script and view it in your browser:
<?php
 
// include class
include("Numbers/Words.php");
 
// create object
$nw = new Numbers_Words();
 
// convert to string
echo "600 in words is " . $nw->toWords(600);
 
?>

Here's the output the code produces:
600 in words is six hundred

As you might imagine, this isn't a very complicated class to use. There's one main method, toWords(), which accepts a number as argument and outputs the corresponding string. You can alter it to use number units different from the standard U.S. ones if you like, by passing an additional locale parameter (more on that later).

Negative thinking
The Numbers_Words class can handle both large values, and negative integers. Here's an example:
<?php
 
// include class
include("Numbers/Words.php");
 
// make list of numbers
$numbers = array(190000000, 637, 104500, -8730);
 
// create object
$nw = new Numbers_Words();
 
// print numbers in words
foreach ($numbers as $n)
{
       echo "$n in words is " . $nw->toWords($n) . "<br />";
}
 
?>

Here is the output:
190000000 in words is one hundred ninety million
637 in words is six hundred thirty-seven
104500 in words is one hundred four thousand five hundred
-8730 in words is minus eight thousand seven hundred thirty

Money talk
The toWords() method can only handle integers, not decimals. You might consider this a fatal flaw, as I did originally, until I found the toCurrency() method, which is designed specifically to create word equivalents for currency (including fractional) amounts:
<?php
 
// include class
include("Numbers/Words.php");
 
// create object
$nw = new Numbers_Words();
 
// convert to currency string
echo "600.75 in words is " . $nw->toCurrency(600.75);
 
?>

The output is what you'd expect:
600.75 in words is six hundred dollars seventy-five cents

Native language
An interesting, and very useful, feature of the Number_Words class is its ability to print local equivalents for both numbers and currency. This is accomplished by adding an extra, optional argument in the toWords() and toCurrency() calls. For example, here's code to write "three million" in French:
<?php
 
// include class
include("Numbers/Words.php");
 
// create object
$nw = new Numbers_Words();
 
// convert to string
echo "3000000 in words is " . $nw->toWords(3000000, 'fr');
 
?>

And the output from that is:
3000000 in words is trois millions

This works with currency also:
<?php
 
// include class
include("Numbers/Words.php");
 
// create object
$nw = new Numbers_Words();
 
// convert to currency string
echo "3000000.50 in words is " . $nw->toCurrency(3000000.50, 'en_US', 'CHF');
 
?>

This is a little more complicated. The first argument to toCurrency() is the number to be converted (note that decimals work here); this is followed by the locale for which the string is to be displayed (here, U.S.), and then the currency units to use (here, Swiss francs or CHF). Here's the result:
3000000.50 in words is three million Swiss francs five rapps

Locale-specific data for a number of countries ships with the class. If your country isn't in the list, it's very simple to create a locale file for your custom needs; simply copy any of the existing language files and edit to use local equivalents. And don't forget to send a copy to the maintainer of the class, so that it can be included in the next distribution.

The real world
Now, how about using everything you just learned in a real-world script? Consider the following case: I needed a script to display a printable statement containing a list of all the items sold to a particular customer during the month. The list of sold items was stored in a MySQL database, indexed by date and customer code; all I had to do was retrieve it, make it look pretty, add up the numbers and display the total amount in words and figures. Listing A contains the code.

Note my use of the Numbers_Words class here. After adding up all the purchases and subtracting payments from that amount, the remainder constitutes the pending amount to be paid by the customer. This amount is printed in both numbers and words, using the toCurrency() method explained earlier. Here is a sample report generated by the script in Listing A.

I hope you find the code useful, and that you can use the Numbers_Words class to save some time the next time you build an invoicing application.

Editor's Picks

Free Newsletters, In your Inbox