Skip to content

Instantly share code, notes, and snippets.

@chrismilson
Last active February 3, 2021 00:22
Show Gist options
  • Save chrismilson/48840cc4b77a56ee1caa9196ae1cc649 to your computer and use it in GitHub Desktop.
Save chrismilson/48840cc4b77a56ee1caa9196ae1cc649 to your computer and use it in GitHub Desktop.
Numbers to Words

Numbers to Words

demo

I am currently an English teacher at some schools in Japan and recently my students have been learning how to write the numbers in words in English. For example, if they were given the number 12 they are learning to write 'twelve'.

One of the questions I set the students was to find the number with the longest length (in characters; 4 would be bigger than 10 because four has more characters than ten) and I wanted to be able to check the answers that the students gave me.

There are a lot of resources online for calculating the string associated with a number however most of these resources use the American style; without 'and'. As I am not American I wanted to use 'and', so I implemented my own itoa method that would take an integer input and return a string, that was hopefully the correct way of writing the number in words in English.

# The empty strings in these arrays make it easier to access the values by the
# result of a division etc.
# The value for the ones digit
# Since the teens are irregular, they are treated as ones.
__one = [
'',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen'
]
# The strings for the tens digits
__ten = [
'',
'',
'twenty',
'thirty',
'forty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety'
]
# Strings for the different powers of 1000
# We can add more values here to increase the cap on the size of the number
__power = [
'',
'thousand',
'million',
'billion',
'trillion',
'quadrillion',
'quintillion',
'sextillion',
'septillion',
'octillion',
'nonillion',
'decillion'
]
def __threeDigits(n):
# split off the hundreds digit
h, t = divmod(n, 100)
if t >= 20:
# if the tens digit is not a teen treat it normally and split off the ones.
t, o = divmod(t, 10)
else:
# let the ones digit handle the teens.
t, o = 0, t
result = []
if h > 0:
result.append(__one[h])
result.append('hundred')
if t > 0 or o > 0:
# If there is a number that *might* need an and, give it one.
result.append('and')
if t > 0 and o > 0:
result.append(__ten[t] + '-' + __one[o])
elif t > 0:
result.append(__ten[t])
else:
result.append(__one[o])
return result
def __helper(num, power):
# If the number is zero it will not affect the output
if num == 0:
return []
big, small = divmod(num, 1000)
# Recurse to name the big stuff first and then add the small stuff
result = __helper(big, power + 1) + __threeDigits(small)
# If there is no small stuff, dont add the power
# Otherwise we will get things like 1000000 returning one million thousand.
if small > 0 and power > 0:
result.append(__power[power])
return result
def itoa(num):
# If the number is zero, the helper function will not help us because
# we want to make sure numbers like 1000 dont return strings like 'one
# thousand zero'
if num == 0:
return 'zero'
# The powers array contains the names for each power of 10^3 that we want to
# calculate. If the number would require anything more than that, raise an
# error.
if num >= 10 ** (3 * len(__power)):
raise ValueError(f"The number {num} is too big to represent in words.")
# Hand the number to the helper method
result = __helper(num, 0)
# The helper method places an 'and' before every non-zero tens number. We will
# want all of these unless it is at the beginning.
if result[0] == 'and':
result.pop(0)
return ' '.join(result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment