Numbers to Words

4th of May, 2008

I wrote a little code snippit the other day to warn readers about posts further down the page, which may not be safe to have on your screen at work. This was a really simple exercise, but it really bugged me that this short warning message always began with a digit. To me, that just wasn't reader-friendly enough.

That's when I got a little carried away, and wrote a function which converts numbers to their fully-expanded written form. I did try to find something built-into PHP to use first, but all I could find to do this was a PEAR module which I wasn't about to install just so I could do this.

I googled around a bit and found that someone had written a rather long function to achieve what I wanted, but it was so long and painful-looking that even though I'm not much of a coder, I decided to write my own. Well, after getting it to the point where it handles numbers in the hundreds of millions, mine isn't exactly short either, but it's about half the length of the one I found.

What it Does

It simply converts numbers into their respective word-forms.  Usage is as follows:

n2w(string $number [, string $format])

The optional format parameter is a single character (either 'l', 't' or 'f') which tells the function whether you'd like your words in lower case (default), title case, or to capitalise just the first letter.

For example:

n2w('32562798','f');

returns:

Thirty-two million, five hundred and sixty-two thousand, seven hundred and ninety-eight

The function does not output anything, so you will probably want to 'echo' its results, unless you plan to process it further.

You can give it a number of any length but it will only use the last nine digits of it, which should really be plenty for every concievable purpose.  It breaks down the number by treating it as a string of characters which is progressively trimmed.  Although it ivolves looping through the string, it doesn't have to do that for every digit, as each loop triggers a bunch of the conditionals.

Here it is:

/* NUMBERS TO WORDS by Milorad Ivovic (ivovic.net) - GPL
     $number is given as a string and can be any length,
        but only the last 9 digits will be processed.
     $format can be:
        l - lowercase (default)
        t - makeshift title case
        f - capitalise first character only  */
function n2w($number, $format='l') {
  if (is_numeric($number)) $original = $number;
  else return 0;
  while ($number) {
    // Trim numbers that are too large
    if (strlen($number)>=10) $number = substr($number,1);
    // Process millions
    if (strlen($number)==7) {
      $thisdigit=substr($number,0,1);
      if ($thisdigit) $words .= n2w_digit($thisdigit).' million';
      elseif (substr($original,-8,1) || substr($original,-9,1)) $words .= ' million';
      if (substr($number,1,1)) $words .= ', ';
      $number = substr($number,1);
    }
    // Process thousands
    if (strlen($number)==4) {
      $thisdigit=substr($number,0,1);
      if ($thisdigit) $words .= n2w_digit($thisdigit).' thousand';
      elseif (substr($original,-5,1) || substr($original,-6,1)) $words .= ' thousand';
      if (substr($number,1,1)) $words .= ', ';
      $number = substr($number,1);
    }
    // Process hundreds, hundreds of thousands, and hundreds of millions
    if (strlen($number)==3 || strlen($number)==6 || strlen($number)==9) {
      $thisdigit=substr($number,0,1);
      if ($thisdigit) $words .= n2w_digit($thisdigit).' hundred';
      if (substr($number,1,1) || substr($number,2,1)) $words .= ' and ';
      $number = substr($number,1);
    }
    // Process tens, tens of thousands, and tens of millions
    if (strlen($number)==2 || strlen($number)==5 || strlen($number)==8) {
      $thisdigit = substr($number,0,1);
      if ($thisdigit>1) { // not teens
        $words .= n2w_tens($thisdigit);
        // hyphenate unless next digit is zero
        if (substr($number,1,1)) $words .= '-';
        $number = substr($number,1);
      }
      elseif ($thisdigit==1) { // dealing with teens
        $words .= n2w_teens(substr($number,0,2));
        if (strlen($original)==5) $words .= ' thousand';
        if (strlen($original)==8) $words .= ' million';
        $number = substr($number,2); // trim by 2 digits
      }
      else $number = substr($number,1); // no tens, as in '405'
    }
    if (strlen($number)==1) {
      $thisdigit = substr($number,0,1);
      if (strlen($original)==1 || $thisdigit) $words .= n2w_digit($thisdigit);
      $number = ''; // kill the number, end the loop.
    }
  }
  if ($words) { // output (returns, does not echo)
    if ($format=='f') return ucfirst($words);
    elseif ($format=='t') return ucwords($words);
    else return $words;
  }
  else return 0;
}
function n2w_tens($ten) {
  if ($ten=='2') return 'twenty';
  if ($ten=='3') return 'thirty';
  if ($ten=='4') return 'forty';
  if ($ten=='5') return 'fifty';
  if ($ten=='6') return 'sixty';
  if ($ten=='7') return 'seventy';
  if ($ten=='8') return 'eighty';
  if ($ten=='9') return 'ninety';
}
function n2w_teens($teen) {
  if ($teen=='10') return 'ten';
  if ($teen=='11') return 'eleven';
  if ($teen=='12') return 'twelve';
  if ($teen=='13') return 'thirteen';
  if ($teen=='14') return 'fourteen';
  if ($teen=='15') return 'fifteen';
  if ($teen=='16') return 'sixteen';
  if ($teen=='17') return 'seventeen';
  if ($teen=='18') return 'eighteen';
  if ($teen=='19') return 'nineteen';
}
function n2w_digit($digit) {
  if ($digit=='0') return 'zero';
  if ($digit=='1') return 'one';
  if ($digit=='2') return 'two';
  if ($digit=='3') return 'three';
  if ($digit=='4') return 'four';
  if ($digit=='5') return 'five';
  if ($digit=='6') return 'six';
  if ($digit=='7') return 'seven';
  if ($digit=='8') return 'eight';
  if ($digit=='9') return 'nine';
}

The function correctly skips zero values unless given as a single digit.  For instance:

n2w('0');

returns:

zero

and:

n2w('2008');

returns:

two thousand and eight

If anyone ends up using this, I'd love to know what for, or if you've made any improvements.

I use Wordpress, so I've just tossed this into my theme's 'functions.php' and employed it in various places such as the number of comments displayed on pages like this one.

I can't believe someone is charging $20 for a one-megabyte windows executable that does this.

Two Responses

  1. #1 5th of August, 2008 at 00:49

    Классно, штука полезная!

  2. #2 21st of August, 2008 at 23:10

    Респект.

Respond Now

Comments are Gravatar enabled

Fields marked * are required.

Allowed XHTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Close
E-mail It