Skip to content

Instantly share code, notes, and snippets.

@adorsk
Created April 24, 2015 18:51
Show Gist options
  • Save adorsk/ea8d5a327148389394e3 to your computer and use it in GitHub Desktop.
Save adorsk/ea8d5a327148389394e3 to your computer and use it in GitHub Desktop.
Numbah Convertah
#!/usr/bin/env python
"""
Number-to-spoken-numbers converter.
"""
max_value = 10**66 - 1
big_words = {
3: "thousand",
6: "million",
9: "billion",
12: "trillion",
15: "quadrillion",
18: "quintillion",
21: "sextillion",
24: "septillion",
27: "octillion",
30: "nonillion",
33: "decillion",
36: "undecillion",
39: "duodecillion",
42: "tredecillion",
45: "quattuordecillion",
48: "quindecillion",
51: "sexdecillion (sedecillion)",
54: "septendecillion",
57: "octodecillion",
60: "novemdecillion (novendecillion)",
63: "vigintillion",
}
exponents = big_words.keys()
ones_words = ['one', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine']
teens_words = {
10: 'ten',
11: 'eleven',
12: 'twelve',
13: 'thirteen',
14: 'fourteen',
15:'fifteen',
16: 'sixteen',
17: 'seventeen',
18: 'eighteen',
19: 'nineteen'
}
tens_words = ['twenty', 'thirty', 'fourty', 'fifty', 'sixty', 'seventy',
'eighty', 'ninety']
def num_to_words(n):
"""return the english spoken-language representation of a non-negative
integer. max value: 10^66 - 1.
>>> num_to_words(3)
'three'
>>> num_to_words(12)
'twelve'
>>> num_to_words(355)
'three hundred fifty five'
>>> num_to_words(1051213)
'one million fifty one thousand two hundred thirteen'
>>> num_to_words(-1)
Traceback (most recent call last):
...
ValueError: n must be a non-negative integer
>>> num_to_words("biscuits")
Traceback (most recent call last):
...
ValueError: n must be a non-negative integer
>>> num_to_words(10**66)
Traceback (most recent call last):
...
OverflowError: that's a huuuuuuuge number, too big for me!
"""
# check for max value
if isinstance(n, long) and n > max_value:
raise OverflowError("that's a huuuuuuuge number, too big for me!")
# check for positive int.
if not isinstance(n, int) or n < 0:
raise ValueError("n must be a non-negative integer")
if n == 0:
return 'zero'
# iteratively build the string.
words = []
for exponent in reversed(exponents):
divisor = 10**exponent
int_part = n/divisor
if int_part > 0:
words.extend(small_num_to_words(int_part) +
[big_words[exponent]])
n -= int_part * divisor
words.extend(small_num_to_words(n))
return " ".join(words)
# helper function for numbers > 0, < 1000.
def small_num_to_words(small_n):
words = []
hundreds = small_n/100
if hundreds > 0:
words.extend([ones_words[hundreds-1]] + ['hundred'])
small_n %= 100
if small_n >= 10 and small_n < 20:
words.append(teens_words[small_n])
else:
tens = small_n/10
if tens > 1:
words.append(tens_words[tens-2])
ones = small_n % 10
words.append(ones_words[ones-1])
return words
if __name__ == "__main__":
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment