Convert numbers to words in English and Asian format
Introduction
I was going through the articles and ran into an article that
showed the conversion of number to words, such as 12 to Twelve. I though let me try same thing but in a
different way. I am not a programmer but like to monkey around with codes.
Anyways, the
Converter
class allows us to convert the numbers into words. Let the picture talk! Background
Before digging into the code let’s see how the numbers are
read in word
In English Style:
123,123,000 = One hundred twenty three million one hundred twenty three thousand
123,000,000 = One hundred twenty three million
123,000 = One hundred twenty three thousand
As we can see the three set of numbers are
always spelled same way and then the modifier, like million is appended. In
English style numbers are aggregated in a group of three. In Asian style it’s
little bit different. The last (towards right) three are grouped together and
then rests of the numbers are aggregated with two words.123,123,000 = One hundred twenty three million one hundred twenty three thousand
123,000,000 = One hundred twenty three million
123,000 = One hundred twenty three thousand
In Asian Style:
12,12,123 = Twelve lakh twelve thousand one hundred twenty three
12,00,000 = Twelve lakh
12,000 = twelve thousand
123 = one hundred twenty three
Code Flow
The absolute common thing between these two systems is the digit. 1 is one, 9 is nine and 20 is twenty in both. And the difference is how the higher numbers are grouped and read. To facilitate these I created arrays. These arrays are the heart of the conversion. The tricky part is to find the index so that we can use these arrays.
Collapse |
Private SingleDigitStringArray() As String = _
{"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"}
Private DoubleDigitsStringArray() As String = _
{"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}
Private TenthDigitStringArray() As String = _
{"Ten", "Eleven", "Tweleve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}
Private HigherDigitEnglishStringArray() As String = _
{"", "", "Hundred", "Thousand", "Million", "Billion", "Trillion", "Quadrillion", "Quintillion"}
Private HigherDigitAsianStringArray() As String = _
{"", "", "Hundred", "Thousand", "Lakh", "Karod", "Arab", "Kharab"}
Private EnglishCodeArray() As String = {"1", "22", "3"}
Private AsianCodeArray() As String = {"1", "22", "3", "4", "42", "5", "52", "6", "62", "7", "72", "8", "82"}
The entire process is basically array manipulation. The primary
goal is to find the correct index corresponding to the number and its position and
then pulling the corresponding word out of the array shown above.
Let’s get the ball rolling. In English conversion method, we work 3 digits at a time from right side and then affix the thousand/million as necessary and loop until we are done, as shown below:
Let’s get the ball rolling. In English conversion method, we work 3 digits at a time from right side and then affix the thousand/million as necessary and loop until we are done, as shown below:
Collapse |
Do
concatHigherDigitString = False
If i > 3 Then concatHigherDigitString = True 'to suffix the Thousand/Million/Billion type of Word
If newAmount.Length >= 4 Then 'work with 3 right most digits at a time
newAmount = amountString.Substring(amountString.Length - i, 3)
End If
'do the conversion and affix the Thousand/Million/Billion type of word at the end when needed
If concatHigherDigitString AndAlso CInt(newAmount) <> 0 Then
result = ThreeDigitsConverter(CInt(newAmount)) & " " & _
HigherDigitEnglishStringArray(i / 3 + 1) & " " & result
Else
result = ThreeDigitsConverter(CInt(newAmount))
End If
workedStringLength += newAmount.Length
newAmount = amountString.Substring(0, amountString.Length - workedStringLength)
i += 3
Loop Until amountString.Length <= workedStringLength
In both of the method, we first convert the given number to string and then to an array, for instance, 1234 to “1234” and then to {1, 2, 3, 4}, using following simple code. I believe there must be a better way of doing this…
Collapse |
'convert numbers to array of each digit
Dim amountArray(amountString.Length - 1) As Integer
For i As Integer = amountArray.Length To 1 Step -1
amountArray(i - 1) = amountString.Substring(i - 1, 1)
Next
Now we work on digit by digit but backwards as the digit in
unit place remains in unit place all the time.
Things get little complicated when working with numbers like 12 because
it’s not read like onetwo however as Twelve. Similarly, 22 is not twotwo but
Twenty two. Likewise, 10001 is not Ten thousand zero hundred one but it’s Ten thousand one.
Keeping all these in minds, following loop will find the right index and then
from the words library (fields array that we talked about earlier) we convert
the digits to word.
Collapse |
For i As Integer = amountArray.Length To 1 Step -1
j = amountArray.Length - i
digit = amountArray(j)
codeIndex = EnglishCodeArray(i - 1)
higherDigitEnglishString = HigherDigitEnglishStringArray(CInt(codeIndex.Substring(0, 1)) - 1)
If codeIndex = "1" Then 'Number [1 9]
result = result & separator & SingleDigitStringArray(digit)
ElseIf codeIndex.Length = 2 And digit <> 0 Then 'Number in tenth place and skip if digit is 0
If digit = 1 Then 'Number [Eleven, Twelve,...., Nineteen]
Dim suffixDigit As Integer = amountArray(j + 1)
result = result & separator & TenthDigitStringArray(suffixDigit) & " " & higherDigitEnglishString
i -= 1 'Skip the next round as we already looked at it
Else 'Number [tenth] and [20+]
result = result & separator & DoubleDigitsStringArray(digit) & " " & higherDigitEnglishString
End If
ElseIf digit <> 0 Then 'Standard Number like 100, 1000, 1000000 and skip if digit is 0
result = result & separator & SingleDigitStringArray(digit) & " " & higherDigitEnglishString
End If
separator = " "
Next
During the process a space or two get attached in between
the words so for the cleanup I use the
RegEx
as:
Collapse |
Private Function RemoveSpaces(ByVal word As String) As String
Dim regEx As New System.Text.RegularExpressions.Regex(" ")
Return regEx.Replace(word, " ").Trim
End Function
There we go, this will convert the numbers to digits!
Using the code
Simply
create a new instance of the converter and pass the number you want to convert
and the conversion style and call the Convert method.
Blocks of code should be set as style "Formatted" like this:
Collapse |
Dim converter As New Converter(number, converter.ConvertStyle.English)
Me.RichTextBox1.Text = converter.Convert
converter = New Converter(number, NumberToWords.Converter.ConvertStyle.Asian)
Me.RichTextBox2.Text = converter.Convert
Points of Interest
These
two arrays are worth mentioning
Collapse |
Private EnglishCodeArray() As String = {"1", "22", "3"}
Private AsianCodeArray() As String = {"1", "22", "3", "4", "42", "5", "52", "6", "62", "7", "72", "8", "82"}
…these two arrays help to determine whether a digit is in unit
place or, tenth place and so on… In the above array, double digit like “22” will
always represent the 10th place. “4” will represent thousand and “42” will
represent ten thousand.
Somewhere I have a feeling I have not done enough testing so comments
are actually what I am expecting. Thanks!
0 comments: