0 Replies - 407 Views - Last Post: 03 August 2014 - 05:46 AM

#1 dbasnett  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 109
  • View blog
  • Posts: 603
  • Joined: 01-October 08

Convert Integers to Words

Posted 03 August 2014 - 05:46 AM

The following code will convert most integers(all except Long.MinValue) to words.

Examples:
2,147,483,647 two billion, one hundred forty-seven million, four hundred eighty-three thousand, six hundred forty-seven
-2,147,483,647 negative two billion, one hundred forty-seven million, four hundred eighty-three thousand, six hundred forty-seven
1,402,176,086 one billion, four hundred two million, one hundred seventy-six thousand, eighty-six
1,567,844,707 one billion, five hundred sixty-seven million, eight hundred forty-four thousand, seven hundred seven
-19 negative nineteen
1,888,888,888 one billion, eight hundred eighty-eight million, eight hundred eighty-eight thousand, eight hundred eighty-eight
888,685,580 eight hundred eighty-eight million, six hundred eighty-five thousand, five hundred eighty
1 one

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 > 0 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


This post has been edited by dbasnett: 10 August 2014 - 04:25 AM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1