Introduction
There are many solutions to converting numbers to words, the best one is a
matter of choice, the bigger the number, the more you have to deal with, or do
you!
If you think that the bigger the number, the more you have to do, then you would
be wrong because the size of the number does not really matter, it is how you
write your functions / methods that matter most.
Lets look at a number 678934.34, what are its properties?
There is a whole number and a decimal (fraction) part; the whole number part is
made up of sets of 3 numbers, 678 and 934, if the number of characters in a
particular set is 3, then that set of numbers can be written as hundreds,
tens/teens or units if the number of characters in a set is only 2 then it will
always be written as tens/teens and nits.
For example:
934 is written as "Nine hundred Thirty Four" or "Nine hundred Thirteen" if the
number was 913, whether it is thousands, millions or trillions does not really
matter, simply that any set of three (3) numbers is always written in either
way.
So if any set of three numbers is written the same, how do we deal with
thousands, millions, billions, the answer here is really simple, there is no
rocket science to it.
The very first thing that needs to be done is declare the arrays of words
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
"ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
"ninety"
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen"
"hundred","thousand","million","billion","trillion","quadrillion","quintillion",
...
The first thing to do with whole numbers is to split the number into sets of
numbers filling an array in reverse order;
678934 is clearly 2 sets of 3 numbers 678 and 934 so lets create an array with
two elements
string[]
numberSet = new string[2];
always do this in reverse order, the last set is always the first in, get it!
numberSet[0] =
"934"
numberSet[1] = "678"
At this point we know that each set of three numbers follows the same rule, that
is hundred, tens/teens or units no matter where in the chain they exists.
Simple, isn't it!
What's next?
Easy as, element 0 is ALWAYS hundreds, element 1 is ALWAYS thousands, element 2
is ALWAYS millions, can you see where I am going!
No, hmmm, ok numberSet[0] translates to "Nine hundred Thirty Four" and
numberSet[1] translates to "Six hundred Seventy Eight" right!
Remember we created the array of words, one of these arrays deals with the "BIG"
names, so lets call the array bigNames,
By now you should know that the whole number in words is "Six hundred Seventy
Eight Thousand, Nine hundred Thirty Four" (depending on which convention you
use, US or UK)
So how do we get from knowing the words from the sets of three numbers to the
whole number words, again very easily,
string
the wholeNumberWords = ""
for(int
i = numberSet.Length; i > 0; i--)
{
wholeNumberWords = numberSet[i] + " " +
bigNames[i] + ", ";
}
Using this approach we have:
numberSet[0] translates to "Nine hundred Thirty Four" and
numberSet[1] translates to "Six hundred Seventy Eight"
numberSet[1] translates to "Six hundred Seventy Eight"
bigNames[1] translates to "thousand"
numberSet[0] translates to "Nine hundred Thirty Four" and
bigNames[0] translates to "hundred"
Put these together and we get, numberSet[1] + bigNames[1] + numberSet[0] +
bigNames[0], in words "Six hundred Seventy Eight Thousand, Nine hundred Thirty
Four"
Of course there are a lot of things you need to do to get to this point like,
making the task a little easier by declaring an array of wordSets, this array
will contain the
elements of the translated number sets (wordSets, [0] = "Nine hundred Thirty
Four")
You also need to have functions / methods to translate each character of a
numberSet eg;
string
words(string number)
{
string n="",
s="";
for(int
i=0; i<3; i++)
{
n = numberSet[0].SubString(i, 1); //this does not take
into account other factors, you will need to learn what the other conditions
are...
s += unitsArray[Int.Parse(n)-1];
}
//the result is
//n = "9", s = unitsArray[9-1], s = unitsArray[8], s = "nine"
//n = "3", s = unitsArray[3-1], s = unitsArray[2], s = "three / thirty" (depends
on other factors for testing conditions)
//n = "4", s = unitsArray[4-1], s = unitsArray[3], s = "four"
}
Ok we have looked at sets of numbers that can be treated as whole numbers of 3
but 012 is a set of three yet the word expected here is twelve not zero one two
so what do you
do for these cases?
The first thing is to get rid of the 0 at position 1 because we do not say zero
hundred and twenty three, we simply say twenty three or using 012 as an example,
we say
twelve, so what are the conditions for whole numbers of two characters. (lets
assume the number is 032)
The first condition is, is the number in the tens range (ten, twenty, thirty
...) or in the teens range (eleven, twelve, thirteen ...) if its in the tens
range then we need
to look at the first character of the number and address the tens array @
element[n-1] n-1 being the first digit in the whole number, once we have the
word from the tens range
wee need to look at the 2nd character of the whole number to determine which
element in the units array we address, so if the character is a "2" we get the
word at units[n-1]
in words, 032 becomes units[2] + " " + units[1] = " thirty two"
On the other hand, if the whole number is in the teens range (assume the number
is 017) then we can completely ignor the last character in the number (7) and
simply address
the teens array at element[(n-1)-10] in this case element[6] = "seventeen"
But if the whole number is "10" then it is clearly not in the teens and you
cannot assume that the word should be translated to a unit word, we need to look
at the last
character of the whole number, if it is a zero (0) then it can be ignored and
the word for the whole number comes from the tens array at element[n-1], in this
case element[0] = "ten"
Millions| thousands | hundreds | . |decimal|
-------------------------------------
| 6 | 7 | 8 | 9 | 3 | 4 | . | 3 | 4 |
-------------------------------------
| | |
| | -- Units "one", "two", "three", "four", "five", "six", "seven", "eight",
"nine"
| |
| ------ Tens / Teens "ten", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety" OR
| "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen"
|
|--------- Hundreds from Units + the word "hundred" (six + hundred )
-------------------------------------
Millions| thousands | hundreds | . |decimal|
-------------------------------------
| |
| -- "HUNDRED","thousand","million","billion","trillion","quadrillion","quintillion",
...
|
|------------ "hundred","THOUSAND","million","billion","trillion","quadrillion","quintillion",
...
When you have all the words representing the sets of numbers you can build the
final string representing the number you want to translate to words.
Up to this point I have talked about whole numbers, what about the fraction or
the decimal part of the number, this can be treated much the same way except
that the conditions for testing will depend on the number being either a
currency or a general number.
If the number is a currency then we need to look at the teens array or the units
array only for example if the decimal part of a number is .56 then for currency
we want to see fifty six but for a general number it is commonly worded as five
six or point five six however, if the number is currency and the number past the
decimal place is greater than 2 then the wording should be (assume .5672 cents)
point five six seven two cents not fifty six seven two cents however you could
do a little more condition testing and do something like fifty six point seven
two cents.
When the number has been processed, it is time to assemble the words for the
final output string, do this by traversing the words array in reverse order
obtaining the big numbers name from the bigNumbers array based on the array
position, bigNumbers[i-1]
string
assembleWords()
{
int
i;
tring a;
for(i
= words.Length; i > 0; i--)
{
a += words[i-1] + " ";
if(i
> 1)
a += bigNumbers[i-1] +
", ";
}
return(a);
}
The return value here is the words for the whole number so there is one thing
left to do here, if it is currency then we attach the currency name for example
"dollars" or "pounds", "drakma" etc.
Next step is to attaché the fraction/decimal words to complete the translation,
in this case
Six hundred Seventy Eight Thousand, Nine hundred Thirty Four Dollars and
Thirty Four Cents
Summary:
-
Break apart the number you want to translate
into it's elements
-
Store the sets of numbers in an array of
number sets making sure that the first nset of numbers in is the last set of
numbers in the word
-
Test each set of numbers from the numbers
array and place them into a words array corresponding with the elements of
the numbers array
-
Build the word string using the words array.
Conclusion:
Converting a number to words is easy; all you need to do is understand the
process to do it with, if you do it right, the same code to convert 3 numbers
will also convert a number whose length exceeds the Centillion value (10^303)
the googolplex is one such value;
1 Googol = 10 ^100
1 Googolplex = 1 ^Googol, this is one hell of a number and lets not even go
there…
The attached application is written in C++
It will convert any number to the centillion value and does not require a DLL,
I have given you enough for you to write your own class but if you are unwilling
to do that, I have written a DLL which can be called from your C# code, this is
available to you for a small fee ($10US)