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
    Jefferson City, MO
    Posts
    9,764

    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

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
  •  



Click Here to Expand Forum to Full Width