Convert Numbers Into Words

Originally posted at python-forum.org by redmarvell

"""Numbers to Words
- converts Numbers to their verbal equivalent"""
# Marianne Williams 12 OCT 2007 Toronto, Ontario
# This program may be used, reproduced, stored or transmitted
# entirely or partially only if the redmarvel (Marianne Williams)
# is acknowledged in the credit / blame for this code
untbl = {'1':'One','2':'Two','3':'Three','4':'Four','5':'Five',
         '6':'Six','7':'Seven','8':'Eight','9':'Nine'}
teentbl = {'0':'Ten','1':'Eleven','2':'Twelve','3':'Thirteen','4':'Fourteen','5':'Fifteen',
           '6':'Sixteen','7':'Seventeen','8':'Eighteen','9':'Nineteen'}
dectbl = {'2':'Twenty','3':'Thirty','4':'Forty','5':'Fifty',
          '6':'Sixty','7':'Seventy','8':'Eighty','9':'Ninety'}
bmth = {2:'Billion',1:'Million',0:'Thousand',
        3:"Trillion",4:"Quadrillion",5:"Quintillion",6:"Sextillion",
        7:"Septillion",8:"Octillion",9:"Nonillion",10:"Decillion"}

def NumberToWords(amt):
    words = ''
    amt = str(amt)
    new_amt = '' # amount to convert
    prefix = '' # previous characters
    for a in amt:
        if a.isdigit():
            if new_amt == '':
                new_amt = prefix
                prefix = ''
            new_amt += a
        elif a in ('-','$','.') and new_amt == '':
            prefix += a
        elif a in ('.',',') and new_amt != '':
            new_amt += a
        else:
            new_amt,prefix,words = AppendString(new_amt,prefix,words)
            words += a
    new_amt,prefix,words = AppendString(new_amt,prefix,words)
    words = words.strip()
    return words

def AppendString(new_amt,prefix,words):
    new_words = ''
    c = ''
    if new_amt != '':
        new_words = ChangeToWords(new_amt) + ' '
        new_amt = ''
    elif prefix != '':
        new_words = prefix
        prefix = ''
    if words != '' and new_words != '':
        words = words.strip()
        c = ' '
    words += c + new_words
#    if new_words != '':
#        words += ' '
    return new_amt,prefix,words

def ChangeToWords(amt):
    words = ''
    orig_amt = amt
    amt = amt.replace(',','')
    pos = ''
    c = ''
    if amt[0:1] == '$':
        amt = amt[1:] # remove dollar sign
    elif amt[0:2] == '-$':
        amt = '-' + amt[2:]
        orig_amt = '$' + amt
    test = amt.split('.')
    dollars = test[0]
    test = orig_amt.split('.')
    cents = ''
    num_commas = orig_amt.count(',')
    if len(test) > 1:
        cents = test[1]
    try:
        amt = float(amt) # convert string to number
    except:
        return orig_amt
    if amt == '': amt = 0
    minus = False
    if amt < 0:
        amt = 0 - amt
        minus = True
    if len(dollars) > 34:
        len_c = len(orig_amt)
        for c in range(0,len_c):
            use_num = orig_amt[c:c+1]
            if use_num == '0':
                words += ' Zero'
            elif use_num == ',':
                words += ' comma'
            elif use_num in untbl:
                words += ' ' + untbl[use_num]
    elif dollars != '' and test[0] != '':
        len_d = len(dollars)
        c = ''
        pos = int(len_d / 3)
        spos = 0
        epos = len_d - (pos * 3)
        while pos > 0:
            if spos < 0: spos = 0
            if epos > len_d: epos = len_d
            parse = dollars[spos:epos]
            pos = pos - 1 # bmth position
            words,c = ParseAmt(words,parse,pos,c)
            spos = epos
            epos += 3
        spos = len_d - 3
        if spos < 0: spos = 0
        hundreds = dollars[spos:len_d]
        pos = ''
        words,c = ParseAmt(words,hundreds,pos,c)
        if words == '':
            words = 'Zero '
    if orig_amt[0:1] == '$' and dollars:
            words += 'dollars '
    if cents and len(cents) < 3 and cents[0:1] != '0':
        cents = cents.ljust(2,'0')
        if orig_amt[0:1] == '$' and dollars:
            words += 'and '
        elif orig_amt[0:1] != '$':
            words += 'point '
            c = ''
        words,c = ParseAmt(words,cents,pos,c)
        if orig_amt[0:1] == '$':
            words += 'cents'
    elif cents and cents != '':
        words += 'point'
        len_c = len(cents)
        for c in range(0,len_c):
            cent = cents[c:c+1]
            if cent == '0':
                words += ' Zero'
            else:
                words += ' ' + untbl[cent]
    if minus:
        words = 'Minus ' + words
    words = words.strip()
    return words

def ParseAmt(words,value,pos,c):
    phrase = ''
    if value != '0' and value:
        if len(value) > 2:
            phrase,value,c = ParseHundreds(phrase,value,c)
        if len(value) == 2:
            phrase,value,c = ParseTens(phrase,value,c)
        if len(value) == 1:
            #if pos == '' and words != '': c = 'and '
            phrase,value = ParseOnes(phrase,value,c)
    if phrase != '' and pos in bmth:
        phrase = phrase + bmth[pos] + ' '
        c = 'and '
    words += phrase
    return words,c

def ParseHundreds(words,value,c):
    upos = value[0:1]
    if upos in untbl:
        words += untbl[upos] + ' Hundred '
        c = 'and '
    value = value[1:3]
    return words,value,c

def ParseTens(words,value,c):
    upos = value[0:1]
    if upos == '1':
        tpos = value[1:2]
        if tpos in teentbl:
            words += c
            words += teentbl[tpos] + ' '
            c = ''
        value = ''
    else:
        if upos in dectbl:
            words += c
            words += dectbl[upos] + ' '
            c = ''
        value = value[1:2]
    return words,value,c

def ParseOnes(words,value,c):
    upos = value[0:1]
    if upos in untbl:
        words += c
        words += untbl[upos] + ' '
    return words, value
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.