13
\$\begingroup\$

I cobbled together a function from various sources that takes an integer and returns it as its respective English word formatted as a string. The function is as follows:

def int2word(num, separator="-"):
    """Transforms integers =< 999 into English words

    Parameters
    ----------
    num : int
    separator : str

    Returns
    -------
    words : str
    """
    ones_and_teens = {0: "Zero", 1: 'One', 2: 'Two', 3: 'Three',
                      4: 'Four', 5: 'Five', 6: 'Six', 7: 'Seven',
                      8: 'Eight', 9: 'Nine', 10: 'Ten', 11: 'Eleven',
                      12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen',
                      15: 'Fifteen', 16: 'Sixteen', 17: 'Seventeen',
                      18: 'Eighteen', 19: 'Nineteen'}
    twenty2ninety = {2: 'Twenty', 3: 'Thirty', 4: 'Forty', 5: 'Fifty',
                     6: 'Sixty', 7: 'Seventy', 8: 'Eighty', 9: 'Ninety', 0: ""}

    if 0 <= num < 19:
        return ones_and_teens[num]
    elif 20 <= num <= 99:
        tens, below_ten = divmod(num, 10)
        if below_ten > 0:
            words = twenty2ninety[tens] + separator + \
                ones_and_teens[below_ten].lower()
        else:
            words = twenty2ninety[tens]
        return words

    elif 100 <= num <= 999:
        hundreds, below_hundred = divmod(num, 100)
        tens, below_ten = divmod(below_hundred, 10)
        if below_hundred == 0:
            words = ones_and_teens[hundreds] + separator + "hundred"
        elif below_ten == 0:
            words = ones_and_teens[hundreds] + separator + \
                "hundred" + separator + twenty2ninety[tens].lower()
        else:
            if tens > 0:
                words = ones_and_teens[hundreds] + separator + "hundred" + separator + twenty2ninety[
                    tens].lower() + separator + ones_and_teens[below_ten].lower()
            else:
                words = ones_and_teens[
                    hundreds] + separator + "hundred" + separator + ones_and_teens[below_ten].lower()
        return words

    else:
        print("num out of range")
\$\endgroup\$

2 Answers 2

23
\$\begingroup\$

There's an easier way.

We have the num2words module which can be easily installed via pip:

pip install num2words

The advantage of this module is that it supports multiple languages:

  • en (English, default)
  • fr (French)
  • de (German)
  • es (Spanish)
  • lt (Lithuanian)
  • lv (Latvian)
  • en_GB (British English)
  • en_IN (Indian English)
  • no (Norwegian)
  • pl (Polish)
  • ru (Russian)
  • dk (Danish)
  • pt_BR (Brazilian Portuguese)

More, you can even generate ordinal numbers like forty-second.

A small python example for converting numbers to words using num2words looks like this:

>>> from num2words import num2words
>>> num2words(42)
forty-two
>>> num2words(42, ordinal=True)
forty-second

You can read more about what you can do using this module here


NOTE: In case somebody is wondering why this is not a code review (such as comments on the posted code), is because in the unedited question the author specifically asked if there is already a library for this.

\$\endgroup\$
3
  • 7
    \$\begingroup\$ Well that is just cheating... +1 \$\endgroup\$ Commented Mar 1, 2017 at 18:59
  • 3
    \$\begingroup\$ Well, in the un-edited question the author specifically asked if there is already a library for this. \$\endgroup\$
    – ChatterOne
    Commented Mar 1, 2017 at 22:12
  • 1
    \$\begingroup\$ @ChatterOne IDK why that got edited out. Are we not supposed to ask about libraries here? So many rules :/ \$\endgroup\$ Commented Mar 2, 2017 at 5:35
11
\$\begingroup\$

You have quite a big bug there. In this part:

elif 100 <= num <= 999:
    hundreds, below_hundred = divmod(num, 100)
    tens, below_ten = divmod(below_hundred, 10)

If you have anything where the last two digits are less than 20, it's going to fail because the result is going to be 1 and 10 - that number (if you have 19, you'll get 1 and 9), which leads to a KeyError.

So, any number like 119, 315, 417 and so on will make it fail. I'd say stick with the num2words that @Dex'ter suggested or be prepared to do quite some debugging.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.