Converts longs > Long.MinValue to words. The code uses recursion FWIW.
Code:
Public Class NumberToWords
''' <summary>
''' Convert any Long (except Long.MinValue) to words
''' </summary>
''' <param name="someNum">the number to be converted</param>
''' <param name="negativePrefix">the prefix to use if the number is negative</param>
''' <returns>string representation of number</returns>
''' <remarks>won't convert Long.MinValue</remarks>
Public Shared Function Convert(someNum As Long, Optional negativePrefix As String = "negative") As String
'convert using NumToString
Return NumToString(someNum, 0, negativePrefix)
End Function
Private Shared Function NumToString(num As Long, level As Integer, Optional negativeprfx As String = "") As String
'on entry level represents the recursive depth
'Debug.Write(level & " ")
Dim rv As New System.Text.StringBuilder
Dim workingNum As Long = num 'working number
Const appender As String = ", "
Const entyAppender As String = "-" 'for hyphens on the 'entys 20, 30, 40, etc
'for this to work the number must be positive
'and greater than Long.MinValue
If workingNum = Long.MinValue Then
Throw New ArgumentException("Can't convert Long.MinValue")
End If
'the negative, if any is
'fixed at the end
Dim isNeg As Boolean = False
If workingNum < 0L Then
isNeg = True
workingNum = -workingNum 'convert to positive if needed
'or
'old school
'reverse the bits and add one
'workingNum = workingNum Xor &HFFFFFFFFFFFFFFFFL
'workingNum += 1L
End If
'is the number known?
rv.Append(Defined(workingNum))
If rv.Length = 0 Then 'known?
'no
'the groups defined as long
'so that the results don't have to be converted
Dim ones As Long = 0L
Dim tens As Long = 0L
Dim hundreds As Long = 0L
Dim thousands As Long = 0L
Dim millions As Long = 0L
Dim billions As Long = 0L
Dim trillions As Long = 0L
Dim quadrillions As Long = 0L
Dim quintillions As Long = 0L
'get count of each grouping
'decreasing workingNum by the grouping total
'only during the first call to this method
'can the number be > 999
If level = 0 Then
quintillions = workingNum \ NumWords.quintillion
workingNum -= quintillions * NumWords.quintillion
quadrillions = workingNum \ NumWords.quadrillion
workingNum -= quadrillions * NumWords.quadrillion
trillions = workingNum \ NumWords.trillion
workingNum -= trillions * NumWords.trillion
billions = workingNum \ NumWords.billion
workingNum -= billions * NumWords.billion
millions = workingNum \ NumWords.million
workingNum -= millions * NumWords.million
thousands = workingNum \ NumWords.thousand
workingNum -= thousands * NumWords.thousand
'now check each group
'and recursively call
'on the groups amount which will be < 1000
If quintillions > 0L Then
rv.Append(NumToString(quintillions, level + 1))
rv.Append(" ")
rv.Append(NumWords.quintillion.ToString)
rv.Append(appender)
End If
If quadrillions > 0L Then
rv.Append(NumToString(quadrillions, level + 1))
rv.Append(" ")
rv.Append(NumWords.quadrillion.ToString)
rv.Append(appender)
End If
If trillions > 0L Then
rv.Append(NumToString(trillions, level + 1))
rv.Append(" ")
rv.Append(NumWords.trillion.ToString)
rv.Append(appender)
End If
If billions > 0L Then
rv.Append(NumToString(billions, level + 1))
rv.Append(" ")
rv.Append(NumWords.billion.ToString)
rv.Append(appender)
End If
If millions > 0L Then
rv.Append(NumToString(millions, level + 1))
rv.Append(" ")
rv.Append(NumWords.million.ToString)
rv.Append(appender)
End If
If thousands > 0L Then
rv.Append(NumToString(thousands, level + 1))
rv.Append(" ")
rv.Append(NumWords.thousand.ToString)
rv.Append(appender)
End If
End If
hundreds = workingNum \ NumWords.hundred
workingNum -= hundreds * NumWords.hundred
'special case for tens
'if the number is less than 20
'don't bother dividing by ten
'because all numbers less than 20 are defined
'note: 20 is known but should be treated as a ten
If workingNum > 19L Then
tens = workingNum \ NumWords.ten
workingNum -= tens * NumWords.ten
End If
ones = workingNum 'what is left
If hundreds > 0L Then
rv.Append(NumToString(hundreds, level + 1))
rv.Append(" ")
rv.Append(NumWords.hundred.ToString)
rv.Append(" ")
End If
If tens > 0L Then
'the tens (10, 20, 30 ...) are defined
rv.Append(NumToString(tens * NumWords.ten, level + 1)) ' times ten to get the defined number string
rv.Append(entyAppender)
End If
If ones > 0L Then
rv.Append(NumToString(ones, level + 1))
rv.Append(" ")
End If
End If
'known numbers come directly here
'was the number negative?
If isNeg Then
If negativeprfx.Length <> 1 Then
rv.Insert(0, " ")
rv.Insert(0, negativeprfx)
Else
rv.Insert(0, negativeprfx)
End If
End If
'get rid of trailing spaces and hyphens, if any
Return rv.ToString.TrimEnd(appender.ToCharArray).TrimEnd(entyAppender.ToCharArray)
End Function
Private Shared Function Defined(num As Long) As String
'is the number defined and less than 100
If [Enum].IsDefined(GetType(NumWords), num) AndAlso num < 100L Then
'yes
Return [Enum].GetName(GetType(NumWords), num)
Else
'no
Return ""
End If
End Function
Enum NumWords As Long
zero = 0L
one = 1L
two = 2L
three = 3L
four = 4L
five = 5L
six = 6L
seven = 7L
eight = 8L
nine = 9L
ten = 10L
eleven = 11L
twelve = 12L
thirteen = 13L
fourteen = 14L
fifteen = 15L
sixteen = 16L
seventeen = 17L
eightteen = 18L
nineteen = 19L
twenty = 20L
thirty = 30L
forty = 40L
fifty = 50L
sixty = 60L
seventy = 70L
eighty = 80L
ninety = 90L
hundred = 100L
thousand = 1000L
million = 1000000L
billion = 1000000000L
trillion = 1000000000000L
quadrillion = 1000000000000000L
quintillion = 1000000000000000000L
End Enum
End Class