PDA

View Full Version : Integers to English Conversion (PHP)



Jeff Wheeler
November 6th, 2005, 04:00 PM
Hey,

I wrote this little script to convert any integer greater than 0, and less than a decillion (10^33, but there are probably php integer limitations).


<?php
function makeNumberEnglish ($number) {
// Variables
$phrase = '';
$number = (string) $number;
$values = array();
$words = array();

// Fill integers array
for ($i=strlen($number)-1; $i>=0; $i-=3) {
$values[pow(10,strlen($number)-($i+1))] = (int) substr($number,($i>2)?$i-2:0,($i>2)?3:$i+1);
}

// Places and replacements (backwards to catch largest first)
$places = array_reverse ( array (
1, 1000, 1000000, 1000000000, 1000000000000, 1000000000000000, 1000000000000000000,
1000000000000000000000, 1000000000000000000000000, 1000000000000000000000000000,
1000000000000000000000000000000
) );
$placeReplacements = array_reverse ( array (
'', 'thousand', 'million', 'billion', 'trillion','quadrillion','quintillion','sextillion ',
'septillion','octillion','nonillion'
) );
foreach ($values as $place => $numeral ) {
$placeWord = str_replace($places,$placeReplacements,(int) $place);
if ($numeral!=0) {
$words[$place] = makeHundredsString($numeral) . ' ' . $placeWord;
}
}

$words = array_reverse($words);
$phrase = array_shift($words);
foreach ($words as $word) {
if ($word!='') {
$phrase .= ', '.$word;
}
}

return $phrase;
}

function makeHundredsString ($number) {
if ($number >= 1000 || $number < 0) // Get rid of invalid calls
die ('makeHundredsString() may not recieve a number greater than or equal to 1,000, or less than 0.');

$words = array(); // Hold words to be concatinated
$phrase = ""; // String to concatinate words to
$number = str_pad((string) $number, 3, '0', STR_PAD_LEFT);
$numString = (string) $number;

$digits = array ('', 'one','two','three','four','five','six','seven','e ight','nine');
$tens = array ('','ten','twenty','thirty','forty','fifty','sixty ','seventy','eighty','ninety');
$teens = array ('ten','eleven','twelve','thirteen','fourteen','fi fteen','sixteen','seventeen','eighteen','nineteen' );
for ($i=0;$i<3;$i++) {
$words[] = ($i==1)?$tens[$numString{$i}]:$digits[$numString{$i}];
}

if ($words[1] == 'ten') {
$words[2] = $teens[$numString{2}];
$words[1] = '';
}

// Make sure it is very natural
$phrase = (($words[0]=='')?null:$words[0].' hundred ').
// If number has hundreds place, add it
(($words[0]!=''&&($words[1]!='' || $words[2]!=''))?'and ':null).$words[1].
// If number had a hundreds place, and has either ones or tens too
(($words[2]=='')?null:(($words[1]!='')?'-':null).$words[2]);
// If number is not blank: if tens place is not blank, then put dash,
// else null, then concatinate ones place

return $phrase;
}
?>

Execute it using something like this:


<?=makeNumberEnglish(522);?>

In a minute, I'll try making an html form for y'all to test it out without running it yourself.

Jeff Wheeler
November 6th, 2005, 04:24 PM
I've published the code on my site:

Source:
http://nokrev.com/code/Math/

Preview:
http://nokrev.com/code/Math/preview.php

Joppe
November 6th, 2005, 04:38 PM
Very cool Nokrev .
I just typed in a bunch of stuff .. One hundred and thirty-five -247483648, seven hundred and one billion, two hundred and eighty-nine million, four hundred and ten thousand, eight hundred and seventy-six to be exakt
but why is some numbers ]-247483648[/B] ?

Krilnon
November 6th, 2005, 04:39 PM
That's pretty neat Nokrev! It would be cool if you could make it work with decimals as well, though I don't know how you would want it to be read.

3.125 could be "Three point one two five" or "Three and one-hundred twenty-five thousandths" or "Three and one eighth".

Jeff Wheeler
November 6th, 2005, 04:41 PM
@joppe: It doesn't support negative numbers ;)

@Krilnon: I'll try that later.

Joppe
November 6th, 2005, 04:43 PM
I know it doesnt support negative numbers .. Thats why i didnt put any negative number in it!

Krilnon
November 6th, 2005, 04:44 PM
I'm guessing negative numbers could be added by simply searching for "-" and having the script remove the hyphen and then tack a 'Negative' onto the start of the number.

joppe, wouldn't the error you have be because you're using a number higher than a decillion?

Jeff Wheeler
November 6th, 2005, 04:44 PM
I'm doing that now ;)

icio
November 6th, 2005, 04:45 PM
Negative numbers would be very simple to accomodate for, nokrev. Just evaluate the absolute value and put "Negative" at the start of the output string.

I put in: "92484203948230498234"
and it returned: "Nine -247483648, two hundred and three billion, nine hundred and forty-eight million, twenty-three thousand, nineteen"

Joppe
November 6th, 2005, 04:46 PM
If you type in "2465364565446435345"
It becomes " Two -247483648, four hundred and fifty-six billion, five hundred and forty-four million, sixty-four thousand, eighteen "

Jeff Wheeler
November 6th, 2005, 04:48 PM
I'll try looking at that. Thanks :)

Edit: Fixed negatives.

Seb Hughes
November 6th, 2005, 05:59 PM
Thats pretty nifty Nokrev :D

Jeff Wheeler
November 6th, 2005, 06:06 PM
Thanks ;)

Yeldarb
November 6th, 2005, 06:08 PM
nokrev, the error several people posted is still there ;)

For example, try putting in:
65465452619164185198208

Jeff Wheeler
November 6th, 2005, 06:11 PM
Sorry… I'll try getting to it later. I'm sorta out of time now ;)

paddy.
November 6th, 2005, 06:12 PM
100000000000000

Gives "One thousand, fourteen"

Hmmm...

Jeff Wheeler
November 6th, 2005, 06:14 PM
Heh :lol:

Indeed it does.

The other problem is caused by PHP's loose typing. It's automatically converting it to a floating point number, which my method doesn't support.

Edit: I've added warnings about the bug with floating-point numbers.

senocular
November 6th, 2005, 06:59 PM
I did something similar in Flash a while ago. I think I forgot to consider negative numbers as well :trout:

http://proto.layer51.com/d.aspx?f=622

Jeff Wheeler
November 6th, 2005, 07:26 PM
Of course, yours is about four times as condense as mine, and works more reliably :P

hl
November 8th, 2005, 10:39 PM
"Two billion, one hundred and forty-seven million, four hundred and eighty-three thousand, six hundred and forty-seven"

"1000000000000000000000000000000000000"

even funnier, if i take out some 0's it returns the same thing :P

Jeff Wheeler
November 8th, 2005, 10:50 PM
As I noted earlier, it's caused by PHP's loose data typing. It's converting it to a float, and then my function converts various parts to ints, screwing it up ;)

mathew.er
November 9th, 2005, 04:27 AM
So you might try to divide the string into more than one by javaScript if its too long.

Jeff Wheeler
November 9th, 2005, 08:01 PM
Nah… I already do that, I just need to support floats when doing it, and make sure to cut off the decimal. I also use PHP to do it, splitting it into hundreds. Why would I use js?

icio
November 10th, 2005, 02:44 AM
I think using BCMath might be the way to go. I looked into last night and it seems to be able to do what you're after.

BCMath:
http://uk2.php.net/manual/en/ref.bc.php
:thumb: