Thursday, October 25, 2007

Convert Number (Currency) to Word - Part I

On many accounting software, sometimes you need to convert the current number to words. This can be done by make a function which will return a string of number given by input parameter. The function itself actually is very easy to make, if you want basic converting of course. The interesting part is that each developer has unique way to make this algorithm. And because it's wide solution that can be produced, this problem often used by programming courses to make their students understand about algorithm.

To make a good number to word converter, first we must understand how to pronounce those words. In this part, we will make an English converter. Part II will have an Indonesian converter.

Basic Understanding

First rule of converting number is to know the prefix. In English, the common prefixes are hundred, thousand, million, billion, and trillion. I called these by "level". So, we need 5 type of level, right ? Well, not quite right. Actually, we only need 4 type of level. Hundred can be repeated in every level. Ex: 1100 (One thousand one hundred), and 1000100 (One Million One hundred). Now, let's make a function for this level.

Code 1
Private Shared Function EnglishLevel(ByVal level As String) As String
Dim retval As String = ""

Select Case level
Case 0
retval
= "thousand "
Case 1
retval
= "million "
Case 2
retval
= "billion "
Case 3
retval
= "trillion "
End Select

Return retval
End Function

Now me will create a default number to word function. This function will return a string represent the number given in it's parameter. You can see the snippet in code 2.







Code 2

Private Shared Function EnglishNumber(ByVal num As String) As String
Dim retval As String = ""

Select Case num
Case 1
retval
= "one"
Case 2
retval
= "two"
Case 3
retval
= "three"
Case 4
retval
= "four"
Case 5
retval
= "five"
Case 6
retval
= "six"
Case 7
retval
= "seven"
Case 8
retval
= "eight"
Case 9
retval
= "nine"
End Select

Return retval
End Function

Pattern Understanding


Before we make the main function, we should think about the pattern algorithm first and design the function. In this section, I'll explain about how the algorithm works.


The first pattern that you should know, is that within the prefix, the word is repeat them self. Lets see this example: 123,123 (One hundred twenty three thousand one hundred twenty three). Even for 123,123,123; the pattern will be same. All you have to add is only the prefix. By analyze this pattern, we only need a function to define the prefix (which I already add in above), and a function to define the number, and repeat itself. For my solution, I'll use a recursion and playing with reference passing and default math functions.


The second and third patterns are "ty" and "teen" prefix. Some numbers don't change their pronunciations ("sixty"/"sixteen", "seventy"/"seventeen"), but some does change ("fifty"/"fifteen" not "fivety"/"fiveteen"). Luckily, some of those numbers won't have a specific word between "ty" and "teen". Three exceptions are for 10, 11, and 12. Therefore, we should modify our EnglishNumber function from Code 2 in to this.







Code 2 - Revised.

Private Shared Function EnglishNumber(ByVal num As String, _
ByVal special As Boolean) As String
Dim retval As String = ""

Select Case num
Case 1
retval
= "one"
Case 2
If special Then
retval
= "twen"
Else
retval
= "two"
End If
Case 3
If special Then
retval
= "thir"
Else
retval
= "three"
End If
Case 4
retval
= "four"
Case 5
If special Then
retval
= "fif"
Else
retval
= "five"
End If
Case 6
retval
= "six"
Case 7
retval
= "seven"
Case 8
If special Then
retval
= "eigh"
Else
retval
= "eight"
End If
Case 9
retval
= "nine"
End Select

Return retval
End Function

Make Main Function


Finally, all we need is the main function that will be called. Remember that we only need to parse 3 number each prefix, since it will repeat after a prefix was given. For this method, I'll use a recursive approach.


First, we separate hundreds with "\". Second, we will decide whether we need "ty" or "teen". The last one, we will use recursive until we have 3 digits of number.


Additional function that we should add, is the ability to say in either formal English (UK) or non formal English (US). The difference is only the use of "and". In UK, 110 should read "One hundred and ten", while in US, it's ok if you only say "One hundred ten". You can see the code 3 below.







Code 3


Public Shared Function NumberToEnglishWords(ByVal num As Long, _
ByVal level As Integer, _
Optional ByVal Official As _
Boolean = True) As String
Dim retval As String = ""

Dim pInt As Long = num Mod 1000

If pInt > 99 Then
retval
= retval & EnglishNumber(pInt \ 100, False) & " hundred "
End If

pInt
= pInt Mod 100

If pInt > 0 And num \ 100 > 0 And Official = True Then
retval
= retval & "and "
End If

If pInt > 19 Then
retval
= retval & EnglishNumber(pInt \ 10, True) & "ty " & _
EnglishNumber(pInt
Mod 10, False)
ElseIf pInt = 10 Then
retval
= retval & "ten"
ElseIf pInt = 11 Then
retval
= retval & "eleven "
ElseIf pInt > 11 Then
retval
= retval & EnglishNumber(pInt Mod 10, True) & "teen "
ElseIf pInt = 12 Then
retval
= retval & "twelve "
Else
retval
= retval & EnglishNumber(pInt Mod 10, False)
End If

If num \ 1000 > 0 Then
If num \ 1000 Mod 1000 > 0 Then
retval
= NumberToEnglishWords(num \ 1000, level + 1) & " " & _
EnglishLevel(level)
& retval
Else
retval
= NumberToEnglishWords(num \ 1000, level + 1) & retval
End If
End If

Return retval
End Function

That's all. Just call the main function, and it will return the number in string variable. Next part, I'll explain about how to convert number to word in Indonesian Language.


You can download the code here.

2 comments:

Anonymous said...

Well written article.

Ecommerce web development said...

Great code... I will implement this code in future. So informative post, I hope to see more articles similar to this. Thanks for sharing.