Placement Prep

Number to Words: Python Program and Algorithm

Convert any integer to its English-word equivalent in Python. Step-by-step algorithm, verified worked examples, and complete code for number-to-words conversion.

By FACE Prep Team 5 min read
python number-to-words algorithm placement-prep coding-practice programming

Number-to-words conversion splits an integer into groups of three digits, maps each group to English words, then concatenates the parts with the correct scale suffix.

This pattern comes up in placement coding rounds and in practical applications such as generating invoice amounts in text form. It is a useful exercise because it combines list indexing, integer arithmetic, and a recursive helper into a single coherent program. This article uses the international naming convention (ones, thousands, millions, billions) throughout. The Indian convention (lakhs, crores) uses the same algorithm with a different scale list; that variant is noted in the FAQ.

Two Naming Conventions: Pick One Before Coding

The two common conventions differ in how they name numbers at and above ten thousand:

NumberInternationalIndian
1,00,000one hundred thousandone lakh
10,00,000one millionten lakh
1,00,00,000ten millionone crore
1,23,45,678one hundred twenty-three million four hundred fifty-six thousand seven hundred eightytwelve crore thirty-four lakh fifty-six thousand seven hundred eighty

Mixing conventions mid-function is the most common mistake. Choose one before writing a single line. The Python implementation below uses the international convention because placement platforms that ask for this problem (TCS iOCL, AMCAT coding, InfyTQ) typically expect international grouping and test with inputs that make the distinction visible.

The Three Lookup Lists

The algorithm needs three lists:

  • Ones (indices 0 through 19): Covers zero through nineteen. Indices 11 through 19 hold the teen words (eleven, twelve, …, nineteen) because those are not compositional from a tens word plus a units word. Index 0 is an empty string, used when a digit position contributes nothing.
  • Tens (indices 0 through 9): Holds the words for multiples of ten: twenty at index 2, thirty at index 3, and so on. Indices 0 and 1 are empty strings because numbers below 20 are handled entirely by the ones list.
  • Scale (indices 0 through 3): Holds the group suffixes: an empty string at index 0 (ones group), then thousand, million, billion at indices 1, 2, 3.

The Python built-in functions str() and len() appear later in the implementation to derive a digit count, but the core logic depends only on these three lists and standard integer arithmetic.

ones = [
    "", "one", "two", "three", "four", "five", "six", "seven",
    "eight", "nine", "ten", "eleven", "twelve", "thirteen",
    "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
]

tens_words = [
    "", "", "twenty", "thirty", "forty", "fifty",
    "sixty", "seventy", "eighty", "ninety"
]

scale = ["", "thousand", "million", "billion"]

Converting a 3-Digit Group to Words

Every integer can be broken into groups of at most three digits from the right. The helper function converts a single such group (any integer from 1 to 999) into words:

def three_digits(n):
    """Return the word string for an integer in the range 1–999.
    Returns an empty string for n == 0 (the parent handles zero)."""
    if n == 0:
        return ""
    if n < 20:
        return ones[n]
    if n < 100:
        unit = ones[n % 10]
        return tens_words[n // 10] + ("-" + unit if unit else "")
    hundreds_word = ones[n // 100] + " hundred"
    remainder = three_digits(n % 100)
    return hundreds_word + (" " + remainder if remainder else "")

The logic at each branch:

  • n below 20: return ones[n] directly. This handles 1 through 19 including all the teen words.
  • n between 20 and 99: compute the tens word using integer division (n // 10 gives the tens digit), then append a hyphen and the units word only if the units digit is non-zero. twenty stays twenty; twenty-three appends -three.
  • n of 100 or above: build the hundreds word (ones[n // 100] + " hundred"), then recursively call three_digits on the remainder. 300"three hundred" with no remainder; 345"three hundred forty-five".

This is the same digit-extraction pattern used in the Armstrong number check and the Python calculator program: % 10 isolates the rightmost digit, // 10 drops it.

Full Python Implementation

ones = [
    "", "one", "two", "three", "four", "five", "six", "seven",
    "eight", "nine", "ten", "eleven", "twelve", "thirteen",
    "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
]

tens_words = [
    "", "", "twenty", "thirty", "forty", "fifty",
    "sixty", "seventy", "eighty", "ninety"
]

scale = ["", "thousand", "million", "billion"]


def three_digits(n):
    if n == 0:
        return ""
    if n < 20:
        return ones[n]
    if n < 100:
        unit = ones[n % 10]
        return tens_words[n // 10] + ("-" + unit if unit else "")
    remainder = three_digits(n % 100)
    return ones[n // 100] + " hundred" + (" " + remainder if remainder else "")


def number_to_words(num):
    if num == 0:
        return "zero"
    if num < 0:
        return "negative " + number_to_words(-num)

    parts = []
    group = 0
    while num > 0:
        chunk = num % 1000
        if chunk:
            suffix = (" " + scale[group]) if group > 0 else ""
            parts.append(three_digits(chunk) + suffix)
        num //= 1000
        group += 1

    return " ".join(reversed(parts))


# Test cases
print(number_to_words(0))         # zero
print(number_to_words(100))       # one hundred
print(number_to_words(1000))      # one thousand
print(number_to_words(1234))      # one thousand two hundred thirty-four
print(number_to_words(9923))      # nine thousand nine hundred twenty-three
print(number_to_words(100000))    # one hundred thousand
print(number_to_words(1000000))   # one million
print(number_to_words(1234567))   # one million two hundred thirty-four thousand five hundred sixty-seven
print(number_to_words(-42))       # negative forty-two

The reversed(parts) call is the key structural step. The while loop builds parts in reverse order (ones group first, then thousands, then millions), so reversing the list before joining puts the most significant group first. Python’s list and sequence methods cover reversed() and list.append() in detail if either is unfamiliar.

Worked Examples and Edge Cases

Each example below is verified from first principles, not copied from the original article.

Standard inputs

  • 1234: 1234 % 1000 = 234, three_digits(234) = “two hundred thirty-four”. Then 1234 // 1000 = 1, group = 1, three_digits(1) + " thousand" = “one thousand”. parts = ["two hundred thirty-four", "one thousand"]. Reversed and joined: “one thousand two hundred thirty-four” ✓
  • 9923: 9923 % 1000 = 923. three_digits(923) = ones[9]+” hundred”+” “+three_digits(23) = “nine hundred twenty-three”. Then chunk=9, “nine thousand”. Result: “nine thousand nine hundred twenty-three” ✓
  • 1234567 (1,234,567): group 0: three_digits(567) = “five hundred sixty-seven”; group 1: three_digits(234) + " thousand" = “two hundred thirty-four thousand”; group 2: three_digits(1) + " million" = “one million”. Joined: “one million two hundred thirty-four thousand five hundred sixty-seven” ✓

Boundary multiples

  • 100: three_digits(100) = ones[1]+” hundred”+"" = “one hundred”. The n % 100 = 0 guard prevents a trailing space. ✓
  • 1000: group 0 chunk = 0, skipped. Group 1 chunk = 1, “one thousand”. ✓
  • 100000 (100,000): group 0 chunk = 0, skipped. Group 1 chunk = 100, “one hundred thousand”. ✓
  • 1000000 (1,000,000): groups 0 and 1 are 0, skipped. Group 2 chunk = 1, “one million”. ✓

Edge cases

  • 0: Caught before the loop. Returns “zero” immediately.
  • Negative (-42): Returns “negative ” + number_to_words(42) = “negative forty-two”.
  • 20, 30, … 90: The units guard (if unit else "") ensures no trailing hyphen. three_digits(20) = “twenty” + "" = “twenty”, not “twenty-”. ✓
  • 11 through 19: All return directly from ones[n]. three_digits(11) = “eleven”, not “ten-one”. ✓

For more Python example programs that exercise similar patterns, the practice collection covers palindromes, digit sums, and factorial calculations, all of which share the % 10 / // 10 digit-extraction idiom.


The Indian convention adds two more scale words after “thousand”: lakh (100,000) and crore (10,000,000). Extending the program above to support lakhs and crores is roughly a 15-line change, because the group-splitting logic also needs to change from groups of three to the 2-3-2 pattern. That kind of quick variant experiment, running both versions side by side and checking number_to_words(1234567) against both conventions, is exactly what TinkerLLM is built for at ₹499.

Primary sources

Frequently asked questions

What does the program return for input 0?

The main function checks for zero before entering the loop and returns the string 'zero' immediately. The helper function returns an empty string for a chunk of 0, so 0 must be handled as a special case at the top level.

Why are numbers 11 through 19 handled separately?

The tens-and-units formula breaks down for 11 through 19. 'Ten' + 'one' gives 'ten-one', not 'eleven'. These teen words are not compositional, so the ones list covers indices 0 through 19 with their own unique entries, and the tens branch only applies from 20 onwards.

How do negative numbers work?

The main function checks for a negative input and returns 'negative ' concatenated with the result of calling itself on the absolute value. For example, -123 returns 'negative one hundred twenty-three'.

What is the difference between international and Indian numbering for 1234567?

Under the international convention, 1,234,567 groups as 1 million + 234 thousand + 567, giving 'one million two hundred thirty-four thousand five hundred sixty-seven'. Under the Indian convention, 12,34,567 groups as 12 lakh + 34 thousand + 567, giving 'twelve lakh thirty-four thousand five hundred sixty-seven'.

What is the time complexity of this algorithm?

O(d) where d is the number of digits in the input. The outer loop runs at most four times for inputs up to 999 billion. Each call to the helper function processes at most three digits in constant time, so the total work is proportional to the digit count.

How do I get title-case output like 'One Million Two Hundred'?

Call Python's str.title() method on the return value: number_to_words(1000000).title() returns 'One Million'. The conversion logic is simpler in lowercase; apply title case only at the output stage.

Build AI projects

A self-paced playground for building with LLMs.

TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.

Try TinkerLLM (₹499)
Free AI Roadmap PDF