ONES = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
"sixteen", "seventeen", "eighteen", "nineteen"]
TENS = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
"eighty", "ninety"]
def words(n):
"""Return n (0 <= n < 1 000 000 000) in English words."""
if n < 20: # base case: a single word
return ONES[n]
if n < 100:
rest = "" if n % 10 == 0 else "-" + ONES[n % 10]
return TENS[n // 10] + rest
for size, name in [(1_000_000, "million"), (1000, "thousand"), (100, "hundred")]:
if n >= size:
rest = "" if n % size == 0 else " " + words(n % size)
return words(n // size) + " " + name + rest
for n in [7, 42, 905, 2026, 31_416, 1_000_001, 999_999_999]:
print(n, "->", words(n))
Its checked output is shown in the next box. n // size is the part before the unit word and n % size the part after. Both are smaller than n, so the recursion always reaches a base case. (Cheques in Canada are often written with "and" or with dollars and cents; changing the format only changes the base cases and joining words.)