Convert numbers to words in English and Asian format

6:56:00 am 0 Comments

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!

 IntroImage.png

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.

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.
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:
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…
'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.

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:
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:
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
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: