Converting Numbers To Words Part II

By in VBA on .

See Converting Numbers To Words Part I.

The next test will test 20-99. I think in real TDD, you’re supposed to write tests that test just one thing. But I’m not doing real TDD, so I’m testing in groups.

Sub TEST_Tens()

    Debug.Assert NumbersToWords(20) = "twenty"
    Debug.Assert NumbersToWords(21) = "twenty-one"
    Debug.Assert NumbersToWords(30) = "thirty"
    Debug.Assert NumbersToWords(77) = "seventy-seven"
    Debug.Assert NumbersToWords(99) = "ninety-nine"

End Sub

Again, I’m testing the edges and few in between. Now that I have two test procedures, I’ll need to create a procedure to run them both.

Sub TEST_All()

    TEST_Singles
    TEST_Tens

    Debug.Print "tests passed"

End Sub

Now I can run TEST_All and make sure I don’t break any previous tests with the changes I make. Of course, TEST_Tens fails so it’s time to write some code to make it pass. I tried to write the simplest code possible, but it didn’t work out for me.

Function NumbersToWords(ByVal dNumbers As Double) As String
   
    Dim vaSingles As Variant
    Dim vaTens As Variant
    Dim sReturn As String
   
    vaSingles = Split("zero,one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen", ",")
    vaTens = Split("NA,NA,twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety", ",")
   
    If dNumbers > 19 Then
        sReturn = vaTens(dNumbers \ 10) & "-" & vaSingles(dNumbers - ((dNumbers \ 10) * 10))
    Else
        sReturn = vaSingles(dNumbers)
    End If
   
    NumbersToWords = Trim$(sReturn)
   
End Function

That fails because NumbersToWords(20) returns twenty-zero. So there’s a special case that needs to be handled.

Function NumbersToWords(ByVal dNumbers As Double) As String
   
    Dim vaSingles As Variant
    Dim vaTens As Variant
    Dim sReturn As String
   
    vaSingles = Split("zero,one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen", ",")
    vaTens = Split("NA,NA,twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety", ",")
   
    If dNumbers > 19 Then
        sReturn = vaTens(dNumbers \ 10)
        If dNumbers Mod 10 <> 0 Then
            sReturn = sReturn & "-" & vaSingles(dNumbers - ((dNumbers \ 10) * 10))
        End If
    Else
        sReturn = vaSingles(dNumbers)
    End If
   
   
    NumbersToWords = Trim$(sReturn)
   
End Function

That works. But I can see this special case handling becoming a problem. Maybe. We’ll see what happens when we test in the hundreds.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax