4
\$\begingroup\$

After implementing most of the suggestions from the first question, This is the code I got:

from math import log
zero_to_nineteen = ("zero", "one", "two", "three", "four",
 "five", "six", "seven", "eight", "nine",
 "ten", "eleven", "twelve", "thirteen", "fourteen",
 "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")
tens = ("zero", "ten", "twenty", "thirty", "forty",
 "fifty", "sixty", "seventy", "eighty", "ninety")
# Powers of a thousand (US system of naming)
suffixes = ("zero", "thousand", "million", "billion", "trillion",
 "quadrillion", "quintillion", "sextillion", "septillion",
 "octillion", "nonillion", "decillion", "undecillion",
 "duodecillion", "tredecillion", "quattuordecillion",
 "quinquadecillion", "sedecillion", "septendecillion",
 "octodecillion", "novendecillion", "vigintillion",
 "unvigintillion", "duovigintillion", "tresvigintillion",
 "quattuorvigintillion", "quinquavigintillion", "sesvigintillion",
 "septemvigintillion", "octovigintillion", "novemvigintillion",
 "trigintillion", "untrigintillion", "duotrigintillion",
 "trestrigintilion", "quattuortrigintillion",
 "quinquatrigintillion", "sestrigintillion", "septentrigintillion",
 "octotrigintillion", "noventrigintillion", "quadragintillion")
def spell_out(number):
 """Returns a string representation of the number, in the US system"""
 try:
 number = int(number)
 except OverflowError:
 # This will be triggered with large float values such as 1e584
 return "infinity"
 if number < 0:
 return "negative " + spell_out(-1 * number)
 if number < 20:
 return zero_to_nineteen[number]
 if number < 100:
 tens_digit, ones_digit = divmod(number, 10)
 return _createNumber(tens[tens_digit], ones_digit, "-")
 if number < 1000:
 hundreds_digit, rest = divmod(number, 100)
 return _createNumber(spell_out(hundreds_digit) + " hundred", rest)
 suffix_index = int(log(number, 1000))
 if suffix_index < len(suffixes):
 suffix_value = 1000 ** suffix_index
 prefix, rest = divmod(number, suffix_value)
 prefix = spell_out(prefix) + " " + suffixes[suffix_index]
 return _createNumber(prefix, rest, ", ")
 return "infinity"
def _createNumber(prefix, suffix, seperator=" "):
 # Returns a number with given prefix and suffix (if needed)
 if not isinstance(prefix, str):
 prefix = spell_out(prefix)
 return prefix if suffix == 0 else prefix + seperator + spell_out(suffix)

I'd like to hear any comments about readability/performance/pythonicity and anything else you can think about that could use improving.

asked Aug 12, 2014 at 20:35
\$\endgroup\$
3
  • \$\begingroup\$ One tiny nitpick: in the definition of _createNumber, the variable seperator should be spelt separator. \$\endgroup\$ Commented Aug 14, 2014 at 13:54
  • \$\begingroup\$ Your comment this will be triggered with large float values such as 1e584 isn't exactly correct, as you're actually using int instead of float. \$\endgroup\$ Commented Aug 14, 2014 at 22:57
  • \$\begingroup\$ 1e584 is a float. int(1e584) will raise a OverflowError. Therefore, I am correct in saying that the error will be triggered with large float arguments. \$\endgroup\$ Commented Aug 14, 2014 at 23:18

2 Answers 2

2
\$\begingroup\$

math.log works in floating point and thus has limited precision. On my system at least, your code goes to infinite recursion from spell_out(10**15-1) for example. To avoid this, I would break the number into groups using divmod in a loop.

answered Aug 14, 2014 at 9:28
\$\endgroup\$
1
  • \$\begingroup\$ Annoyingly enough, I did this for the first attempt, but then received a comment that I shouldn't hand-roll my own log function :| \$\endgroup\$ Commented Aug 14, 2014 at 15:00
2
\$\begingroup\$

It looks pretty nice! I can only nitpick.

Instead of:

return "negative " + spell_out(-1 * number)

You could simply:

return "negative " + spell_out(-number)

Some PEP8 recommendations:

  • Use 2 blank lines before each function definition
  • Use snake case in function names, _create_number instead of _createNumber
answered Aug 12, 2014 at 20:48
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.