A simple python script that translates an integer to plain English.
| Python |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | # Copyright (c) 2008 Karan Bhangui <http://karan.bhangui.com/>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import sys, string as str
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):
if int(number) < 100:
return convertDuo(number[1:3])
else:
return ' '.join([ words[int(number[0])], 'hundred', convertDuo(number[1:3]) ])
def convertDuo(number):
#if teens or less
if int(number[0]) <= 1:
return words[int(number)]
#twenty-five
else:
return ''.join([tens[int(number[0]) - 1], '-', words[int(number[1])]])
if __name__ == "__main__":
string = []
numeralSegments = []
numeral = sys.argv[1]
# left-pad number with zeros to make its length a multiple of 3
if len(numeral) % 3 > 0:
numeral = str.zfill( numeral, (3 - (len(numeral) % 3)) + len(numeral) )
# split number into lists, grouped in threes
for i in range (len(numeral), 0, -3):
numeralSegments.append(numeral[i-3:i])
# 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)
|
Discussion
critique appreciated


Comments
Typo on line 58?
Litle bug (using pyhon 2.4.5 on Linux) : python recipe-576577-1.py 100 Traceback (most recent call last): File "recipe-576577-1.py", line 99, in ? string.append(convertTrio(numeralSegments[i]) + ' ' + placeholders[i]) File "recipe-576577-1.py", line 71, in convertTrio return ' '.join([ words[int(number[0])], 'hundred', convertDuo(number[1:3]) ]) File "recipe-576577-1.py", line 77, in convertDuo return words[int(number)] KeyError: 0
I wrote one of these a couple years ago. It's 40% faster than num2words given a 10 digit number as input, and possibly has fewer errors. A clever programmer will extend this to work with decimal objects so that we can play with __format__ and __str__ in derived classes. Thanks.
==> Logic error identified by sebastien.renard. Try numbers input like this---
$ python number_as_word.py 1000 $ python number_as_word.py 1000567
==> Include module __doc__ string that tells how to use program.
==> Well enough written that extending program to include the zero case was trivial.
$ python number_as_word.py 0
This reduces the impact of the logic error.
==> Write "if len(numeral) % 3:" instead of "if len(numeral) % 3 > 3:"
Would you write "if (a == b) is True:"? Well, that sort of thing is common but it doesn't work for me.
==> Don't change name of string module. string module is useful for its character lists, like punctuation. String objects contain the methods, as does the str type (or class, I use python 3). zfill thusly:
==> Avoid overwriting library module names or builtin names. I changed the name of the string variable.
==> Use comprehensions.
==> Write a function so the code can be used as a module.
For what it's worth, my version runs two and a half percent more slowly than does yours. Oh well!
Thank you all for the excellent feedback. I'll make the suggested changes, but more importantly, you've given me ideas on how to become a better pythoner. Cheers!
Sign in to comment