Editor

Number to Words in Python

Beginner · Text and words · about 45 minutes to build · 100 lines

Type a whole number and see it written out in words, in millions and thousands and, for big numbers, in lakh and crore too.

The program

Press Run and answer its questions in the box that appears under the code.

number_to_words.py
"""Number to words: write any whole number up to 999,999,999 in words."""
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"]
LIMIT = 999_999_999
# True: "one hundred and five" (UK, India). False: "one hundred five" (US).
USE_AND = True
# Each system names big groups of digits, largest first.
INTERNATIONAL = [(1_000_000, "million"), (1_000, "thousand")]
INDIAN = [(10_000_000, "crore"), (100_000, "lakh"), (1_000, "thousand")]
# --- Small numbers ---
def below_hundred(n):
"""Write 0-99 in words: 7 -> seven, 42 -> forty-two."""
if n < 20:
return ONES[n]
tens, ones = divmod(n, 10)
return TENS[tens] + ("-" + ONES[ones] if ones else "")
def below_thousand(n):
"""Write 1-999 in words: 305 -> three hundred and five."""
hundreds, rest = divmod(n, 100)
if not hundreds:
return below_hundred(rest)
words = ONES[hundreds] + " hundred"
if rest:
words += (" and " if USE_AND else " ") + below_hundred(rest)
return words
# --- Any number ---
def to_words(n, system):
"""Write a whole number in words using a list of (size, name) groups."""
if n == 0:
return "zero"
if n < 0:
return "minus " + to_words(-n, system)
parts = []
for size, name in system: # peel off millions, then thousands...
count, n = divmod(n, size)
if count:
parts.append(f"{below_thousand(count)} {name}")
if n and parts and n < 100 and USE_AND: # one thousand and five
return " ".join(parts) + " and " + below_hundred(n)
if n:
parts.append(below_thousand(n))
return " ".join(parts)
def indian_commas(n):
"""Group digits the Indian way: 12345678 -> 1,23,45,678."""
sign, digits = ("-" if n < 0 else ""), str(abs(n))
head, tail = digits[:-3], digits[-3:]
pairs = []
while head:
pairs.insert(0, head[-2:])
head = head[:-2]
return sign + ",".join(pairs + [tail])
# --- Talking to the user ---
def parse_number(text):
"""Read a whole number, allowing commas and spaces: "1,234" -> 1234."""
cleaned = text.replace(",", "").replace(" ", "").replace("_", "")
try:
return int(cleaned)
except ValueError:
return None
def main():
"""Convert numbers until the user presses Enter on an empty line."""
print("Number to words")
print(f"Type a whole number up to {LIMIT:,}. Negative numbers work too.")
while True:
text = input("\nNumber (or press Enter to quit): ").strip()
if not text:
print("Goodbye.")
break
n = parse_number(text)
if n is None:
print("That is not a whole number. Try one like 2026 or 1,500.")
elif abs(n) > LIMIT:
print(f"Please stay between -{LIMIT:,} and {LIMIT:,}.")
else:
print(f" {n:,}: {to_words(n, INTERNATIONAL)}")
if abs(n) >= 100_000: # lakh and crore only differ from here up
print(f" {indian_commas(n)} (Indian): {to_words(n, INDIAN)}")
if __name__ == "__main__":
main()

Open it in the full editor to save it, share it and keep building.

Sample run

What the program printed, and what was typed (in yellow).

Number to words
Type a whole number up to 999,999,999. Negative numbers work too.

Number (or press Enter to quit): 7
  7: seven

Number (or press Enter to quit): 42
  42: forty-two

Number (or press Enter to quit): 305
  305: three hundred and five

Number (or press Enter to quit): 2026
  2,026: two thousand and twenty-six

Number (or press Enter to quit): twelve
That is not a whole number. Try one like 2026 or 1,500.

Number (or press Enter to quit): 1,234,567
  1,234,567: one million two hundred and thirty-four thousand five hundred and sixty-seven
  12,34,567 (Indian): twelve lakh thirty-four thousand five hundred and sixty-seven

Number (or press Enter to quit): 999999999
  999,999,999: nine hundred and ninety-nine million nine hundred and ninety-nine thousand nine hundred and ninety-nine
  99,99,99,999 (Indian): ninety-nine crore ninety-nine lakh ninety-nine thousand nine hundred and ninety-nine

Number (or press Enter to quit): -15000
  -15,000: minus fifteen thousand

Number (or press Enter to quit): 
Goodbye.

How it is built

1. Word lists

ONES holds the words for 0 to 19, which English names one by one, and TENS the words for 20, 30 and so on. The position in the list is the number, so ONES[7] is seven.

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"]

2. Below one hundred

Numbers under 20 come straight from ONES. For the rest, divmod(n, 10) splits 42 into 4 and 2, which gives forty-two.

def below_hundred(n):
    """Write 0-99 in words: 7 -> seven, 42 -> forty-two."""
    if n < 20:
        return ONES[n]
    tens, ones = divmod(n, 10)
    return TENS[tens] + ("-" + ONES[ones] if ones else "")

3. Below one thousand

divmod(n, 100) gives the hundreds and the rest. USE_AND chooses between one hundred and five, as said in the UK and India, and the American one hundred five.

def below_thousand(n):
    """Write 1-999 in words: 305 -> three hundred and five."""
    hundreds, rest = divmod(n, 100)
    if not hundreds:
        return below_hundred(rest)
    words = ONES[hundreds] + " hundred"
    if rest:
        words += (" and " if USE_AND else " ") + below_hundred(rest)
    return words

4. Any number

The number is cut into groups from the largest down: millions and thousands, or crores, lakhs and thousands. Each group is below 1,000, so below_thousand writes it, followed by the group's name. A small last group gets and, as in one thousand and five.

def to_words(n, system):
    """Write a whole number in words using a list of (size, name) groups."""
    if n == 0:
        return "zero"
    if n < 0:
        return "minus " + to_words(-n, system)
    parts = []
    for size, name in system:  # peel off millions, then thousands...
        count, n = divmod(n, size)
        if count:
            parts.append(f"{below_thousand(count)} {name}")
    if n and parts and n < 100 and USE_AND:  # one thousand and five
        return " ".join(parts) + " and " + below_hundred(n)
    if n:
        parts.append(below_thousand(n))
    return " ".join(parts)

5. Indian commas

The Indian system groups the last three digits, then pairs of digits: 1,23,45,678. The loop takes two digits at a time from the end of the front part.

def indian_commas(n):
    """Group digits the Indian way: 12345678 -> 1,23,45,678."""
    sign, digits = ("-" if n < 0 else ""), str(abs(n))
    head, tail = digits[:-3], digits[-3:]
    pairs = []
    while head:
        pairs.insert(0, head[-2:])
        head = head[:-2]
    return sign + ",".join(pairs + [tail])

6. Reading the number

Commas, spaces and underscores are removed so 1,500 works, and int() inside try turns anything else into None.

def parse_number(text):
    """Read a whole number, allowing commas and spaces: "1,234" -> 1234."""
    cleaned = text.replace(",", "").replace(" ", "").replace("_", "")
    try:
        return int(cleaned)
    except ValueError:
        return None

Make it bigger

  • Write cheque amounts: add rupees or dollars, the paise or cents, and the word only at the end.
  • Go past a billion by adding billion and trillion to INTERNATIONAL and raising LIMIT.
  • Turn words back into a number, so seven hundred and two gives 702.
  • Write ordinals like twenty-first and one hundredth.

What it practises