Number to Words-VBForums
Results 1 to 1 of 1

Thread: Number to Words

  1. #1

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Pointless Forest 38.517,-92.023
    Posts
    8,912

    Number to Words

    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
    Last edited by dbasnett; Aug 18th, 2014 at 05:59 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- SerialPort Answer

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein
    "They who can give up essential liberty to obtain a little temporary safety, deserve neither liberty nor safety." Benjamin Franklin
    "It is not all that I know that is the problem, it is all I think I do that is."

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.