Skip to content

Instantly share code, notes, and snippets.

@mrphlip
Created September 11, 2016 04:26
Show Gist options
  • Save mrphlip/6073f2fe35b4e2c85b0b033a15865054 to your computer and use it in GitHub Desktop.
Save mrphlip/6073f2fe35b4e2c85b0b033a15865054 to your computer and use it in GitHub Desktop.
English names for numbers
__all__ = ['number_words']
WORDS = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
TENS = [None, None, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
THOUSANDS = {
False: [None, "thousand", "million", "billion", "trillion", "quadrillion", "quintillion" "sextillion", "septillion", "octillion", "nonillion", "decillion", "hendecillion", "dodecillion", "tridecillion", "tetradecillion", "pentadecillion", "hexadecillion", "heptadecillion", "octadecillion", "enneadecillion", "icosillion"],
True: [None, "thousand", "million", "milliard", "billion", "billiard", "trillion", "trilliard", "quadrillion", "quadrilliard", "quintillion", "quintilliard" "sextillion", "septillion", "septilliard", "octillion", "octilliard", "nonillion", "nonilliard", "decillion", "decilliard", "hendecillion", "hendecilliard", "dodecillion", "dodecilliard", "tridecillion", "tridecilliard", "tetradecillion", "tetradecilliard", "pentadecillion", "pentadecilliard", "hexadecillion", "hexadecilliard", "heptadecillion", "heptadecilliard", "octadecillion", "octadecilliard", "enneadecillion", "enneadecilliard", "icosillion", "icosilliard"],
}
def number_words(n, long=False, use_and=True, minus="minus"):
"""
Returns a string of the English name of the given integer.
long: use the long-scale names, where "billion" = "million million".
Default is the short-scale names, where "billion" = "thousand million".
use_and: Include the word "and" in the appropriate places. Typically this
will be off for US speakers, on for UK speakers.
minus: The prefix to use for negative numbers. Default is "minus" but you
can pass "negative" if you want to be pedantic.
"""
if n < 0:
return "%s %s" % (minus, number_words(-n, long, use_and))
if n == 0:
return WORDS[0]
groups = []
while n:
groups.insert(0, n % 1000)
n //= 1000
if len(groups) > len(THOUSANDS[long]):
raise ValueError("Number too large: %d" % n)
bits = []
for i, g in enumerate(groups):
if g:
i = len(groups) - i - 1
if i:
bits.append("%s %s" % (_subthousand(g, use_and), THOUSANDS[long][i]))
else:
bits.append(_subthousand(g, use_and))
if len(bits) > 1 and groups[-1] > 0 and groups[-1] < 100:
return "%s %s%s" % (", ".join(bits[:-1]), "and " if use_and else "", bits[-1])
else:
return ", ".join(bits)
def _subhundred(n):
"""Returns the name of the number n for 0 < n < 100"""
if n >= 20:
if n % 10 != 0:
return '-'.join([TENS[n//10], WORDS[n%10]])
else:
return TENS[n//10]
else:
return WORDS[n]
def _subthousand(n, use_and):
"""Returns the name of the number n for 0 < n < 1000"""
if n >= 100:
if n % 100 != 0:
return "%s hundred %s%s" % (WORDS[n//100], "and " if use_and else "", _subhundred(n % 100))
else:
return WORDS[n//100] + " hundred"
else:
return _subhundred(n % 100)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment