How can I improve this number 2words script

import sys

words = {
    1 : 'one',
    2 : 'two',
    3 : 'three',
    4 : 'four',
    5 : 'five',
    6 : 'six',
    7 : 'seven',
    8 : 'eight',
    9 : 'nine',
    10 : 'ten',
    11 : 'eleven',
    12 : 'twelve',
    13 : 'thirteen',
    14 : 'fourteen',
    15 : 'fifteen',
    16 : 'sixteen',
    17 : 'seventeen',
    18 : 'eighteen',
    19 : 'nineteen'
}

tens = [
    '',
    'twenty',
    'thirty',
    'forty',
    'fifty',
    'sixty',
    'seventy',
    'eighty',
    'ninety',
]

placeholders = [
    '',
    'thousand',
    'million',
    'billion',
    'trillion',
    'quadrillion'
]

# segMag = segment magnitude (starting at 1)
def convertTrio(number):
    return ' '.join([words[int(number[0])],  'hundred',  convertDuo(number[1:3])]) # convertDuo(number[1:3])


def convertDuo(number):
    #if teens or less
    if int(number[0]) == 1:
        return words[int(number)]
    #twenty-five
    else:
        return tens[int(number[0]) - 1] + '-' + words[int(number[1])]


if __name__ == "__main__":

    string = []
    numeralSegments = []
    numeral = sys.argv[1]

    if int(numeral) < 100:
        print convertDuo(numeral)
    else:

        # split number into lists, grouped in threes
        for i in range (0, len(numeral), 3):
            numeralSegments.append(numeral[i:i+3])

        numeralSegments.reverse()

        # for every segment, convert to trio word and append thousand, million, etc depending on magnitude
        for i in range (len(numeralSegments)):
            string.append(convertTrio(numeralSegments[i]) + ' ' + placeholders[i])

        # reverse the list of strings before concatenating to commas
        string.reverse()        
        print ', '.join(string)

Warning . I am a complete newbie in python. I know that there are probably many times more effective ways to do something. I would appreciate any pointers to them.

Change . The code currently only works for numbers whose number of digits is a multiple of three. I would be grateful for the suggestion of an elegant way to fix this. Thank.

+3
source share
6 answers

You cannot group numbers into “segments” going from left to right. range(0,len(),3)won't work well. You will have to write the same algorithm to insert the number separators. You start on the right side by selecting the segments of the digits.

(, ?) 1, 2 3 . convertTrio convertDuo, 3 2 , . - ( ).

,

def segment( n ):
   segList= []
   while len(n) > 3:
       segList.insert( 0, n[-3:] )
       n= n[:-3]
   segList.insert( 0, n )
   return segList

Pythonic, , . if __name__ == "__main__" , .

(, sys.argv, - . " " - . .

if __name__ == "__main__":
    import sys
    for number in sys.argv[1:]:
        print number2string( number )

number2string .

+2

:

  • 40 "", "".

Python doctest unittest.

+3

. 100, .

def convert(n):
    q, r = divmod(n, 10)
    if q < 2:
        return words[n]
    result = tens[q-1] # offset because tens is missing first null value
    if r:
        result += '-' + words[r]
    return result

, , divmod (n, 100) ..

+2

. - 4 2005 .

+1

Number:: Spell Perl. Python ( ).

0

, - , script, inflect.py

import inflect
p = inflect.engine()
p.numwords(123456789)

'one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine'
0

Source: https://habr.com/ru/post/1699559/


All Articles