Created
September 11, 2016 04:26
-
-
Save mrphlip/6073f2fe35b4e2c85b0b033a15865054 to your computer and use it in GitHub Desktop.
English names for numbers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__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