Introduction
A frequent question on programming forums such as Codeguru is how to convert numeric values into written words. It is not as complicated as you may think, but, it is a tad more difficult, or rather, involved. Today, I will show you how to convert numbers into words.
In a previous article, I demonstrated how to convert ordinary numbers into Roman Numerals. The reason I bring this up here is because I will approach this topic in the same manner I did with the Roman Numerals article. I sat long and hard, trying to figure out an easy way to attack this. Not attack per se, but a way to make it easier. Let’s hope I have achieved that goal today.
First, the boring stuff…
Magnitudes
I hope you’re listening, or reading, today, my Mr. Mathematics teacher…
Magnitude in mathematics is the size of a mathematical object. A mathematical object can be compared as smaller or larger (by its size) than other other objects of the same kind. Orders of magnitude are usually written in powers of 10. For example, the order of magnitude of 2700 is, for example, 3. Examples of numbers of different magnitudes can be found on Wikipedia.
Armed with this knowledge, we have a basic setup of how to incorporate these magnitudes into our program. We basically have three objects: ones, tens, and magnitudes.
Our Project
By now, you should know what you will be creating today, so let’s start!
Open Visual Studio and create a new Visual Basic Windows Forms project. There aren’t any controls that you need to add. You can, however, add a new class to your project. I have named my class clsCashtoWords, but you are welcome to name yours differently.
Add the following Namespace because we will be dealing with some text manipulation:
Imports System.Text
Add the following member variables:
Private strMagnitudes() As String = New String() {"", " THOUSAND", " MILLION", _ " BILLION", " TRILLION", " QUADRILLION", " QUINTILLION", " SEXTILLION", _ " SEPTILLION", " OCTILLION", "NONILLION", "DECILLION", "UNDECILLION", _ "DUODECILLION", "TREDECILLION", "QUATTUORDECILLION", "QUINDECILLION", _ "SEXDECILLION", "SEPTENDECILLION", "OCTODECILLION", "NOVEMDECILLION", _ "VIGINTILLION", "CENTILLION"} Private strTens() As String = New String() {"", "", "TWENTY", "THIRTY", _ "FORTY", "FIFTY", "SIXTY", "SEVENTY", "EIGHTY", "NINETY"} Private strUnits() As String = New String() {"", "ONE", "TWO", "THREE", _ "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "ELEVEN", "TWELVE", _ "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTTEEN", _ "NINETEEN"}
Oay, I know I may have gone a bit overboard with the magnitudes… We now have three main objects to work with: Units, Tens, and Magnitudes. Now, add the ShowNumber function:
Public Function ShowNumber(ByVal decInput As Decimal) As String If decInput < 0 Then Throw New ArgumentException("Number must be zero or greater") Dim strNumbers As String = String.Format("{0:f2}", decInput) Dim sbOutput As StringBuilder = New StringBuilder Dim intDecimalDot As Integer = strNumbers.IndexOf("."c) strNumbers = New String("0"c, (3 - (intDecimalDot Mod 3)) Mod 3) & strNumbers intDecimalDot = strNumbers.IndexOf("."c) Dim intHigh As Integer = (intDecimalDot 3) - 1 Dim strDigitGroup() As String = New String(intHigh) {} For i As Integer = 0 To intHigh strDigitGroup(i) = strNumbers.Substring(i * 3, 3) Next i For i As Integer = 0 To intHigh Dim g As String = GroupNumbers(strDigitGroup(i)) If g.Length > 0 Then sbOutput.Append(g & strMagnitudes(intHigh - i) & " ") Next i If sbOutput.ToString.Trim.Length = 0 Then sbOutput = New StringBuilder("ZERO ") Dim cents As String = CalcTens(strNumbers.Substring(strNumbers.Length - 2, 2)) If cents.Length = 0 Then cents = "ZERO" sbOutput.Append("RANDS, " & cents & " CENTS") Return sbOutput.ToString End Function
In the ShowNumber function, I ensured that the input is always positive by throwing an exception when a negative number has been entered. I then identify whether or not there are any decimals present by making use of the string’s IndexOf method.
With the magic of the Mod operator, I identify the highest numbers and start grouping them into magnitudes or tens or units respectively. Here is some more information regarding Visual Basic’s Mod operator.
Now, add the GroupNumbers function:
Private Function GroupNumbers(ByVal strGroup As String, _ Optional ByVal blnAND As Boolean = True) As String strGroup = strGroup.PadLeft(3, "0"c) Dim A As String = "" If Char.IsDigit(strGroup.Chars(0)) Then A = strUnits(Integer.Parse(strGroup.Chars(0))) End If If A.Length > 0 Then A &= " HUNDRED" Dim BC As String = CalcTens(strGroup.Substring(1, 2)) If A.Length > 0 AndAlso BC.Length > 0 AndAlso blnAND _ Then A &= " AND " Return (A & BC).Trim End Function
The GroupNumbers function does what its name implies: It groups the numbers into all their associated groups. This obviously happens after the ShowNumbers function has sorted the numbers into place. It determines whether or not the next character in the list is indeed a number and sorts them into Hundreds. Add the CalcTens function:
Private Function CalcTens(ByVal sTens As String) As String Dim strTemp As String = "" Dim intTen As Integer = Integer.Parse(sTens.PadLeft(2, "0"c)) If intTen < 20 Then strTemp = strUnits(intTen) Else strTemp = strTens(Integer.Parse(sTens.Chars(0))) & " " _ & strUnits(Integer.Parse(sTens.Chars(1))).Trim End If Return strTemp End Function
This function follows the same principle as the previous function; however, it determines where the specific number fits and sorts it into the proper group.
Finally, add the following code for your form:
Private CashWord As clsCashtoWords = New clsCashtoWords() Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load MessageBox.Show(CashWord.ShowNumber(Decimal.Parse("2036.17"))) End Sub
The preceding code creates and instantiates a new clsCashtowords object and calls its ShowNumber method to convert the number 2036.17 into words.
Conclusion
A simple topic such as this can become quite complex. But, by having a good understanding of how numbers work, it becomes a bit easier.