Convert number to word python

num2words library — Convert numbers to words in multiple languages

.. image:: https://img.shields.io/pypi/v/num2words.svg
:target: https://pypi.python.org/pypi/num2words

.. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master
:target: https://travis-ci.org/savoirfairelinux/num2words

.. image:: https://coveralls.io/repos/github/savoirfairelinux/num2words/badge.svg?branch=master
:target: https://coveralls.io/github/savoirfairelinux/num2words?branch=master

num2words is a library that converts numbers like 42 to words like forty-two.
It supports multiple languages (see the list below for full list
of languages) and can even generate ordinal numbers like forty-second
(although this last feature is a bit buggy for some languages at the moment).

The project is hosted on GitHub_. Contributions are welcome.

.. _GitHub: https://github.com/savoirfairelinux/num2words

Installation

The easiest way to install num2words is to use pip::

pip install num2words

Otherwise, you can download the source package and then execute::

python setup.py install

The test suite in this library is new, so it’s rather thin, but it can be run with::

python setup.py test

To run the full CI test suite which includes linting and multiple python environments::

pip install tox
tox

Usage

Command line::

$ num2words 10001
ten thousand and one
$ num2words 24,120.10
twenty-four thousand, one hundred and twenty point one
$ num2words 24,120.10 -l es
veinticuatro mil ciento veinte punto uno
$num2words 2.14 -l es --to currency
dos euros con catorce céntimos

In code there’s only one function to use::

>>> from num2words import num2words
>>> num2words(42)
forty-two
>>> num2words(42, to='ordinal')
forty-second
>>> num2words(42, lang='fr')
quarante-deux

Besides the numerical argument, there are two main optional arguments.

to: The converter to use. Supported values are:

  • cardinal (default)
  • ordinal
  • ordinal_num
  • year
  • currency

lang: The language in which to convert the number. Supported values are:

  • en (English, default)
  • am (Amharic)
  • ar (Arabic)
  • cz (Czech)
  • de (German)
  • dk (Danish)
  • en_GB (English — Great Britain)
  • en_IN (English — India)
  • es (Spanish)
  • es_CO (Spanish — Colombia)
  • es_VE (Spanish — Venezuela)
  • eu (EURO)
  • fa (Farsi)
  • fi (Finnish)
  • fr (French)
  • fr_CH (French — Switzerland)
  • fr_BE (French — Belgium)
  • fr_DZ (French — Algeria)
  • he (Hebrew)
  • hu (Hungarian)
  • id (Indonesian)
  • it (Italian)
  • ja (Japanese)
  • kn (Kannada)
  • ko (Korean)
  • kz (Kazakh)
  • lt (Lithuanian)
  • lv (Latvian)
  • no (Norwegian)
  • pl (Polish)
  • pt (Portuguese)
  • pt_BR (Portuguese — Brazilian)
  • sl (Slovene)
  • sr (Serbian)
  • sv (Swedish)
  • ro (Romanian)
  • ru (Russian)
  • te (Telugu)
  • tg (Tajik)
  • tr (Turkish)
  • th (Thai)
  • vi (Vietnamese)
  • nl (Dutch)
  • uk (Ukrainian)

You can supply values like fr_FR; if the country doesn’t exist but the
language does, the code will fall back to the base language (i.e. fr). If
you supply an unsupported language, NotImplementedError is raised.
Therefore, if you want to call num2words with a fallback, you can do::

try:
    return num2words(42, lang=mylang)
except NotImplementedError:
    return num2words(42, lang='en')

Additionally, some converters and languages support other optional arguments
that are needed to make the converter useful in practice.

Wiki

For additional information on some localization please check the Wiki_.
And feel free to propose wiki enhancement.

.. _Wiki: https://github.com/savoirfairelinux/num2words/wiki

History

num2words is based on an old library, pynum2word, created by Taro Ogawa
in 2003. Unfortunately, the library stopped being maintained and the author
can’t be reached. There was another developer, Marius Grigaitis, who in 2011
added Lithuanian support, but didn’t take over maintenance of the project.

I am thus basing myself on Marius Grigaitis’ improvements and re-publishing
pynum2word as num2words.

Virgil Dupras, Savoir-faire Linux

Changelog

Version 0.5.12 — 2022/08/19

  • Support Japanese Reiwa (令和/れいわ) era. (#412)
  • Add basic farsi support (#354)
  • Added Tajik language support (#406)
  • Fix Amharic language support (#465)
  • Fix Hebrew pluralize and implement to_currency (#330)
  • Add support to translate some currencies in italian language (#434)
  • Fix Polish twenties (#345)
  • Add uzs for ru and en (#422)
  • Added support for Esperanto numbers. (#387)
  • [ADD] to ordinal number for Turkish (#468)
  • Fix zeroth in Dutch to nulde fixing (#326)

Version 0.5.11 — 2022/08/03

  • Add KZT and UAH currencies to lang RU (#264)
  • Add es_NI currency (#276)
  • Update .gitignore to add .eggs/ directory (#280)
  • Fix Hebrew support (#289)
  • Update test_tr.py to increase coverage (#298)
  • Add ordinal 12,345 to ES test suite to increase coverage (#287)
  • Add simple tests for lang_DK.py (#286)
  • Add testcase for lang_EN.py (#288)
  • Add more tests to base.py (#283)
  • Fixed misspelling of 21 (cardinal and ordinal number) in IT language (#270)
  • Romanian issues 259 (#260)
  • Adding Language Support for Telugu / Bug Fix in Kannada (#263)
  • Add support of Kazakh language (KZ) (#306)
  • Update README.rst (#307)
  • Added support for Hungarian language (#310)
  • [UPD] Readme file (#363)
  • [ADD] num2words: add traslation to spanish of several currencies (#356)
  • added swedish language including test cases (#352)
  • Remove dupplicated line in lang_PT_BR (#355)
  • Fix ordinal_num output for Dutch (NL) (#369)
  • Polishordinals (#367)
  • [tr] return Turkish 0 ordinal and cardinal (#347)
  • Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400)
  • feat: ci: replace travis by github workflows (#448)
  • [ES] Added missing accents («dieciséis», «dólar», «dólares», «veintiún»), improved currency gender handling, fixed pound cent names (#443)

Version 0.5.10 — 2019/05/12

  • Add Kannada language localization (#243)
  • Revert some copyrights changed by mistake (#254)
  • Add indian rupee to the supported currencies (#248)
  • Improve currency functions for German and French (#247)
  • Improve Slovene localization (#246)
  • Improve Spanish localization (#240)
  • Fix typo ‘seperator’ on source code (#238)
  • Convert string to decimal values (#223)
  • Improve German localization and test coverage (#237)
  • Improve Polish localization (#233)
  • Fix ordinal number for French ending on 1 (#236)

Version 0.5.9 — 2019/01/10

  • Fix encoding issue on release 0.5.8 (#229)
  • Improve Polish localization (#228)

Version 0.5.8 — 2018/11/17

  • Add Portuguese (Portugal) localization (#198)
  • Add a command line tool to use num2words
  • Use language iso code for Vietnamese
  • Improve Korean localization (#219)
  • Improve Serbian (Latin) localization (#207)
  • Improve testing setup (#220)
  • Improve German localization (#214) (#222)
  • Improve Romanian localization (#215)
  • Improve Spanish localization (#187) (#200)
  • Improve Russian localization (#211) (#212)
  • Improve French localization (23902ab)
  • Improve Arabic localization (#176)
  • Improve Lithuanian and Latvian localization (#185)
  • Improve Ukrainian localization (#183)

Version 0.5.7 — 2018/06/27

  • Add Finnish localization. (#170)
  • Add Japanese localization. (#171)
  • Add belgian-french localization. (#151)
  • Add Czech localization. (#154)
  • Add Thai localization. (#139)
  • Improve English localization. (#144)
  • Improve Spanish localization. (#167)
  • Improve Italian localization. (#143)
  • Improve documentation. (#155, #145, #174)

Version 0.5.6 — 2017/11/22

  • Refactor to_currency (#135)
  • Allow the use of other convertes to_currency, to_year (#95)
  • Fix code to respect PEP8 (#98, #105)
  • Add Slovene localization (#97)
  • Add Ukrainian localization (#93)
  • Add Dutch localization (#91)
  • Add Algeria-French localization (#86)
  • Add Turkish localization (#85)

Version 0.5.5 — 2017/07/02

  • Add Arabic localization (#72)
  • Add Spanish-Colombian and Spanish-Venezuelan localization (#67)
  • Add VietNam localization (#61)
  • Add Italian localization (#56, #59)
  • Improve Russian localization (#62)
  • Improve Polish localization (#58)

Version 0.5.4 — 2016/10/18

  • Tons of new languages!
  • Add Polish localization. (#23)
  • Add Swiss-French localization. (#38)
  • Add Russian localization. (#28, #46, #48)
  • Add Indonesian localization. (#29)
  • Add Norwegian localization. (#33)
  • Add Danish localization. (#40)
  • Add Brazilian localization. (#37, #47)
  • Improve German localization. (#25, #27, #49)
  • Improve Lithuanian localization. (#52)
  • Improve floating point spelling. (#24)

Version 0.5.3 — 2015/06/09

  • Fix packaging issues. (#21, #22)

Version 0.5.2 — 2015/01/23

  • Added Latvian localization. (#9)
  • Improved Spanish localization. (#10, #13, #14)
  • Improved Lithuanian localization. (#12)

Version 0.5.1 — 2014/03/14

  • Added Python 3 support with 2to3. (#3)
  • Fixed big numbers in spanish. (#2)
  • Fixed bugs in tanslation from 30 to 40 in spanish. (#4)
  • Fixed word joining in english. (#8)

Version 0.5.0 — 2013/05/28

  • Created num2words based on the old pynum2word project.

Code for this:

>>>def handel_upto_99(number):
predef={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",20:"twenty",30:"thirty",40:"fourty",50:"fifty",60:"sixty",70:"seventy",80:"eighty",90:"ninety",100:"hundred",100000:"lakh",10000000:"crore",1000000:"million",1000000000:"billion"}
if number in predef.keys():
    return predef[number]
else:
    return predef[(number/10)*10]+' '+predef[number%10]

>>>def return_bigdigit(number,devideby):
predef={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",20:"twenty",30:"thirty",40:"fourty",50:"fifty",60:"sixty",70:"seventy",80:"eighty",90:"ninety",100:"hundred",1000:"thousand",100000:"lakh",10000000:"crore",1000000:"million",1000000000:"billion"}
if devideby in predef.keys():
    return predef[number/devideby]+" "+predef[devideby]
else:
    devideby/=10
    return handel_upto_99(number/devideby)+" "+predef[devideby]

>>>def mainfunction(number):
dev={100:"hundred",1000:"thousand",100000:"lakh",10000000:"crore",1000000000:"billion"}
if number is 0:
    return "Zero"
if number<100:
    result=handel_upto_99(number)

else:
    result=""
    while number>=100:
        devideby=1
        length=len(str(number))
        for i in range(length-1):
            devideby*=10
        if number%devideby==0:
            if devideby in dev:
                return handel_upto_99(number/devideby)+" "+ dev[devideby]
            else:
                return handel_upto_99(number/(devideby/10))+" "+ dev[devideby/10]
        res=return_bigdigit(number,devideby)
        result=result+' '+res
        if devideby not in dev:
            number=number-((devideby/10)*(number/(devideby/10)))
        number=number-devideby*(number/devideby)

    if number <100:
        result = result + ' '+ handel_upto_99(number)
return result

result:

>>>mainfunction(12345)
' twelve thousand three hundred fourty five'
>>>mainfunction(2000)
'two thousand'

In this tutorial, we are going to learn how to convert a number to its wording (digit-wise). For instance, if the number is 12, the wordings will be “one-two”. A similar thing will be done for the rest of the inputs.


Code Implementation

We would be following a number of steps which are mentioned below:


Step 1: Creating a Global list for digit to word mapping

Create a global list containing wordings for each digit from 0 to 9. The list will contain elements mapped to the index as shown in the table below.

Index 0 1 2 3 4 5 6 7 8 9
Wording / Value zero one two three four five six seven eight nine
Global list for digit to word mapping
# Global Array storing word for each digit
arr = ['zero','one','two','three','four','five','six','seven','eight','nine']

Step 2: Taking the input of the number and creating the main function

To take input of the number we will make use of input function and then typecast it to integer and also we will create an empty function that will convert our number to words digit-wise.

# Global Array storing word for each digit
arr = ['zero','one','two','three','four','five','six','seven','eight','nine']

def number_2_word(n):
    pass

n = int(input())
print("Number Entered was : ", n)
print("Converted to word it becomes: ",end="")
print(number_2_word(n))

Step 3: Coding the Main Logic Inside the Function

For this code, we will be making use of Recursion. If you have very little or no knowledge about Recursion I would recommend you to check out the tutorial mentioned below:

Read more on Recursion: Recursion in Python

For every recursive call, we will check if my number became 0, if it did we would return an empty string otherwise we will keep adding the wordings for each digit with the help of the modulus function and divide the number by 10 to shrink the number and move to the next digit.

The code implementation is shown below and comments are added for your understanding.

# Global Array storing word for each digit
arr = ['zero','one','two','three','four','five','six','seven','eight','nine']

def number_2_word(n):

    # If all the digits are encountered return blank string
    if(n==0):
        return ""
    
    else:
        # compute spelling for the last digit
        small_ans = arr[n%10]

        # keep computing for the previous digits and add the spelling for the last digit
        ans = number_2_word(int(n/10)) + small_ans + " "
    
    # Return the final answer
    return ans

n = int(input())
print("Number Entered was : ", n)
print("Converted to word it becomes: ",end="")
print(number_2_word(n))


Outputs:

Number Entered was :  123
Converted to word it becomes: one two three
Number Entered was :  46830
Converted to word it becomes: four six eight three zero 

Conclusion

So by end of this tutorial, we saw that the numbers can easily be converted to the wording (digit-wise) in a pretty easy and simple way by the use of Recursion.

Thank you for reading! Happy Learning! 😇


Improve Article

Save Article

Like Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Like Article

    num2words module in Python, which converts number (like 34) to words (like thirty-four). Also, this library has support for multiple languages. In this article, we will see how to convert number to words using num2words module. Installation One can easily install num2words using pip.

    pip install num2words

    Consider the following two excerpts from different files taken from 20 Newsgroups, a popular NLP database. Pre-processing 20 Newsgroups effectively has remained to be a matter of interest.

    In article, Martin Preston writes: Why not use the PD C library for reading/writing TIFF files? It took me a good 20 minutes to start using them in your own app. ISCIS VIII is the eighth of a series of meetings which have brought together computer scientists and engineers from about twenty countries. This year’s conference will be held in the beautiful Mediterranean resort city of Antalya, in a region rich in natural as well as historical sites.

    In the above two excerpts, one can observe that the number ’20’ appears in both numeric and alphabetical forms. Simply following the pre-processing steps, that involve tokenization, lemmatization and so on would not be able to map ’20’ and ‘twenty’ to the same stem, which is of contextual importance. Luckily, we have the in-built library, num2words which solves this problem in a single line. Below is the sample usage of the tool. 

    Python

    from num2words import num2words

    print(num2words(36))

    print(num2words(36, to = 'ordinal'))

    print(num2words(36, to = 'ordinal_num'))

    print(num2words(36, to = 'year'))

    print(num2words(36, to = 'currency'))

    print(num2words(36, lang ='es'))

    Output:

    thirty-six
    thirty-sixth
    36th
    zero euro, thirty-six cents
    treinta y seis

    Time complexity: O(1).
    Auxiliary space: O(1).

    Therefore, in the pre-processing step, one could convert ALL numeric values to words for better accuracy in the further stages. References: https://pypi.org/project/num2words/

    Like Article

    Save Article

    Converting a number to words is the process of translating a number to words and is an easy process. However, A few rules must be followed when converting a number to words, such as using the correct order and the correct spelling of numbers. 

    Converting numbers into words has many benefits, such as :

    • It helps in understanding and remembering large numbers.
    • It makes it easier to write and read numbers.
    • Useful in many applications, such as writing cheques or displaying numbers on a screen.

    In Python, this can be achieved using the following ways:

    1

    Using the Num2Word library 

    To convert numbers into words using the num2word library, we first have to import the num2word library. And after that, take a number as input from the user using the input() function.

    import num2word
    num = int(input("Enter a number: "))

    Now, to convert the given number into words, use the word() function provided by the num2word module, and after that, print the final result.

    word_number = num2word.word(num)
    print(word_number)

    Here is the complete code in action :

    import num2word
    
    num = int(input("Enter a number: "))
    word_number = num2word.word(num)
    print(word_number)
    
    '''
    #Output
    Enter a number: 653
    Six Hundred Fifty Three
    '''

    2

    Using the inflect library 

    The inflect library is a library for singularizing and pluralizing English words. It can be used to convert a number to its ordinal form, as well as to convert a number to its word form.

    To convert a number to its word form, we can use the number_to_words() method. This method takes an integer as an argument and returns a string. For example, the number_to_words() method will convert the number 100 to its word form, i.e., “one hundred”.

    Here is the python code that uses the inflect library to convert a number to its word form.

    import inflect
    
    number = int(input("Enter the number : "))
    p = inflect.engine()
    word = p.number_to_words(number)
    
    print(number,":",word)
    
    '''
    #Output
    Enter the number : 777
    777 : seven hundred and seventy-seven
    '''

    3

    Creating custom function

    Till now, we have seen the readymade module that Python offers. Now, let’s write a function to translate a number into its corresponding English word representation. 

    For that, We will first need to break the number down into its constituent parts. We can do this by using the modulo operator (%) to find the remainder and integer division (//) to remove the last digit from the number.

    And finally, we will use a series of if-elif-else statements and add a special case for the number zero.

    Here is the complete code in action :

    def convert_to_words(num):
       if num == 0:
           return "zero"
    
       ones = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
       tens = ["", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
       teens = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
    
       num_string = ""
       while num > 0:
           if num < 10:
               num_string += ones[num]
               num = 0
           elif num >= 10 and num <20:
               num_string += teens[num%10]
               num = 0
           elif num < 100:
               num_string += tens[num // 10]
               if num % 10 != 0:
                   num_string += "-" + ones[num % 10]
                   num = 0
           else: #num < 1000:
               num_string += ones[num // 100] + " hundred "
               num %= 100
       return num_string
    
    num = int(input("Enter any number less than 1000 : "))
    
    print(num," : ",convert_to_words(num))
    
    '''
    Enter any number less than 1000 : 54
    54 : fifty-four
    '''

    Using a dictionary to get the English word representation of any given number is another approach; Here, we are declaring the python dictionary, which holds the value and keys.

    And a convert_to_words() method takes one parameter i.e., number. And after that function does the main part of converting that number to its word form.

    Here is the complete code in action.

    #program to convert number into words in Python using a dictionary
    number_words = {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', 20: 'twenty', 30: 'thirty', 40: 'forty', 50: 'fifty', 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety', 100: 'hundred', 1000: 'thousand'}
    
    def convert_to_words(number):
       if number == 0:
           return 'zero'
       if number < 0:
           return 'minus ' + convert_to_words(-number)
       if number < 21:
           return number_words[number]
       if number < 100:
           return number_words[number // 10 * 10] + ' ' + number_words[number % 10]
       if number < 1000:
           return number_words[number // 100] + ' ' + number_words[100] + ' ' + convert_to_words(number % 100)
       for i, k in enumerate(number_words):
           if number < 1000 ** (i + 1):
               return number_words[number // 1000 ** i] + ' ' + number_words[1000 ** i] + ' ' + convert_to_words(number % 1000 ** i)
    
    number = int(input("Enter a number: "))
    print(convert_to_words(number))
    
    '''
    #Output
    Enter a number: 743
    seven hundred forty three
    '''

    Num2Words

    License: MIT
    Python Version

    Convert a number to words. The goal of this repo is to provide a simple
    interface allowing users to convert an integer into its plain English numeral
    form.

    This is an exercise based on the instructions.pdf included
    in this repo.

    Getting Started

    Installation

    Just the package

    You can get started quickly by installing the package straight from Github:

    pip install git+https://github.com/zachzIAM/num-to-words.git@master

    In case the above command is failing, please try using the --user flag to
    avoid user-level permissions issues.

    pip install --user git+https://github.com/zachzIAM/num-to-words.git@master

    Clone the repo

    You can also grab the package by cloning the repo and playing and exploring the
    modules directly. Cloning the repo would let you install the package using
    setup-tools too. You can navigate to the root of the cloned repo via terminal /
    CMD and run:

    Running the tests

    If you do clone the repo you may want to create a new virtual environment for
    the repo and install pytest in it. pytest can then be run on the entire
    tests folder. Navigate to the root of the repository and run:

    Usage

    Command line tool

    Once installed the package exposes a CLI utility called num2words.
    Usage help can be obtained by running:

    num2words has two possible mutually exclusive flags, -n and -f, which
    correspond to operating on a file and operating on an integer passed via the
    command line.

    Parsing ints

    Setting the -n flag primes the utility for work with integers. Here are some
    example calls:

    num2words -n 1
    num2words -n 12
    num2words -n 600
    num2words -n 456
    num2words -n 123456
    num2words -n 198745665132684
    num2words -n 8641563128941534135183451587453354586453141

    Each of these calls will output to terminal the English numeral form of the
    argument.

    Parsing files

    The utility can also work with text file input. Certain rules / assumptions
    apply:

    • the file must contain text rather than binary data
    • only positive integer values embedded in the text will be captured; decimals
      percentages, fractions, big marks, hex values prepended by #, scientific
      notation, etc. will all yield an invalid input response
    • only one numeric value must be present in the input otherwise it will be
      detected as invalid, e.g. cannot have a valid integer and also a decimal
      somewhere else in the same text

    Using num2words on files is as follows:

    num2words -f ./tests/test_inputs/test1.txt
    num2words -f ./tests/test_inputs/test17.txt
    num2words -f ./tests/test_inputs/test18.txt

    Package

    There are two classes the package exposes.

    from num2words import WordNumeral, Num2Words

    The WordNumeral class

    It handles the conversion from a positive int into a plain English numeral.
    Creating a new instance of the object requires a positive integer as input:

    # create object
    n = WordNumeral(456123)
    
    # print will display the English numeral form
    print(n)
    
    # properties
    n.num                                       # original number
    n.numeral                                   # numeral form
    
    # class method - can be called directly from the class
    n.to_numeral(9876543210)                    # from class instance
    WordNumeral.to_numeral(9876543210)          # directly from class
    
    # instances are callable but calls modify them
    print(n.num, ":t", n.numeral)              # before call
    n(123)                                      # call
    print(n.num, ":t", n.numeral)              # after call
    
    # comparison operations
    n2 = WordNumeral(15)
    n2 >= n
    n2 == n
    n2 < n
    n2 != n
    
    # binary operators
    print(n + n2)
    print(n - n2)                               # if negative error will be thrown
    print(n * n2)
    print(n // n2)                              # '/' gives floats so not available
    print(n % n2)
    print(n % n2)
    print(n ** n2)
    print(n << n2)                              # left bit-shift operator
    print(n >> n2)                              # right bit-shift operator
    print(n & n2)                               # bitwise and
    print(n | n2)                               # bitwise or
    print(n ^ n2)                               # bitwise xor

    NOTE! Extended Assignments or Unary operators are currently not implemented!

    the Num2Words class

    This is a client class which is composed of

    • a WordNumeral instance stored as a property called word_numeral
    • a text handler function which takes a string and returns a single integer
      value extracted from the input

    To create an instance of this object the constructor can be called as usual and
    takes an optional custom text handler function. This package has a simple
    default function which can be replaced with custom one of more sophisticated
    behaviour. It is important that any custom definition of the handler function

    • takes a single argument of type str
    • returns a single object of type int
    • if a valid int value to be returned cannot be detected, an
      InvalidNumber (accessible from num2words module) exception must be raised
      in order to be properly handled by the Num2Words class.

    Any instance is callable and the implemented behaviour is modifying. When called
    a file path argument is required and things happen as follows:

    1. contents of the file are are read
    2. handler attempts to extract a valid number from contents
    3. the word_numeral object is called with the extracted number
    4. file path, file contents, handler, word numeral with it’s new properties are
      all stored in the client object
    # create an instance
    client = Num2Words()                            # using default handler
    client("./tests/test_inputs/test1.txt")
    
    # print object
    client                                          # representation of object
    print(client)                                   # custom print method
    
    # properties
    client.num
    client.word_numeral
    client.file_path
    client.file_contents
    
    # instances are callable but calls modify them
    print(client)
    client("./tests/test_inputs/test17.txt")
    print(client)
    
    # use instance method for non-modifying behaviour
    sample_input = "In the year 900 BC an important event took place."
    client.text_to_numeral(sample_input)

    Outline of approach

    In order to parse an integer into English numerals we need to recognise that
    humans do this by reading the number in increments of inc
    thousands, millions, billions, trillions, quadrillions, etc. As we ascend the
    value parsing the n-th increment the rules for converting the number to a
    numeral do not change, e.g thousands range from 1 to 999, so do millions,
    billions, etc.

    This type of problem lends itself very nicely to recursion. The problem can be
    reduced to the following algorithm:

    1. start from the right with significance level 0 (i.e. less than a thousand)
    2. obtain the quotient and remainder for the number when divided by 1000
    3. if the quotient > 0
      1. call function recursively with quotient and significance level
        incremented by 1
      2. otherwise treat as empty string
    4. if remainder > 0
      1. convert to words and append significance name
      2. otherwise treat as empty string
    5. append return value of recursive call to return value of remainder
      conversion and return the combined value

    parse-algorithm

    As the recursion goes deeper we ascend the value until there is no large number
    to process. As the recursion unwinds we obtain the remainder word numeral for
    the highest significance first appending it to the significance name and to the
    the next significance decrement result down. The recursion unwinds completely
    when the remainder conversion with significance level 0 occurs.

    Two helper dictionaries have been set up:

    • _SIG_UNITS to convert the significance levels to words; and
    • _SMALL_NUMS to convert numbers < 1000 to words

    TODO

    Subclassing int

    The API for WordNumeral can be simplified of the class inherits from int. We
    will lose some niceties like __init__ because int is immutable, but it is
    worth forgoing this for the benefit of not having to override every logical
    and arithmetic operator.

    NOTE! Only Comparison and Binary Operators are currently implemented. As
    there is a significant number of them to implement
    we have
    even more incentive to extend int rather than build a class around it.

    Allowing negative integers

    It may also be conceptually cleaner if we allowed for negative integers to be
    valid input for the WordNumeral objects. Not to mention that it is trivial
    to achieve this. The task of capturing and extracting the negative number from
    a body of text is trickier.

    Sphinx documentation

    Although best effort has been put into populating all docstrings as a form of
    documentation, if the package is to be used extensively it may warrant proper
    documentation using Sphinx and
    ReadTheDocs.

    Even larger numbers

    Currently the program can handle numbers as large as largest but no
    larger. I am not certain about the incremental value of this but the
    significance (thousand, million, billion, etc.) words can be abstracted further
    past decillion (decillion) as there is a pattern to how they are
    composed — Extensions of the standard dictionary numbers.
    This logic can be implemented fairly easily by altering the significance
    dictionary to include the component unit names.

    CI / CD

    It would be great to automate building, testing and releasing of the package
    using tools like Travis, Codecov, etc. This will
    significantly improve future development and maintenance.

    Run

    def convert_to_words(num):
     
        l = len(num)
     
        # Base cases
        if (l == 0):
            print("empty string")
            return
     
        if (l > 4):
            print("Length more than 4 is not supported")
            return
     
        single_digits = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
     
        two_digits = ["", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
     
        tens_multiple = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
     
        tens_power = ["hundred", "thousand"]
     
        print(num, ":", end=" ")
     
        if (l == 1):
            print(single_digits[ord(num[0]) - 48])
            return
     
        x = 0
        while (x < len(num)):
            if (l >= 3):
                if (ord(num[x]) - 48 != 0):
                    print(single_digits[ord(num[x]) - 48],
                          end=" ")
                    print(tens_power[l - 3], end=" ")
     
                l -= 1
     
            else:
     
                if (ord(num[x]) - 48 == 1):
                    sum = (ord(num[x]) - 48 +
                           ord(num[x+1]) - 48)
                    print(two_digits[sum])
                    return
     
                elif (ord(num[x]) - 48 == 2 and
                      ord(num[x + 1]) - 48 == 0):
                    print("twenty")
                    return
     
                else:
                    i = ord(num[x]) - 48
                    if(i > 0):
                        print(tens_multiple[i], end=" ")
                    else:
                        print("", end="")
                    x += 1
                    if(ord(num[x]) - 48 != 0):
                        print(single_digits[ord(num[x]) - 48])
            x += 1
     
     
    # Driver Code
    convert_to_words("1121") 
    

    Process

    I’m relatively new to Python, so this may not be the Pythonic approach, but I think it’s useful to use test-driven development for problems like this. Spelling out numbers has lots of special cases, which can be overwhelming, so working incrementally can be one way to get a handle on it.

    I started by writing:

    def main():
      for i in range(0, 20):
        print(f"{i}: {spellNumber(i)}")
    

    This isn’t literally a test, because it doesn’t check the result, but it shows me the output for the first 20 integers, which is where many of the special cases are.

    Then I wrote a simple implementation that uses an array to solve it:

    def spellNumber(n):
      units = ["zero", "one", "two", "three", "four", "five",
               "six", "seven", "eight", "nine", "ten", "eleven",
               "twelve", "thirteen", "fourteen", "fifteen",
               "sixteen", "seventeen", "eighteen", "nineteen"]
      if n < 20: return units[n]
      return "out of range"
    

    Once that appeared to be working, I extended my «test» by sampling values up to 100:

      for i in range(20, 100, 12):
        print(f"{i}: {spellNumber(i)}")
    

    Note that I kept the original part of the test, so that I make sure I don’t break the part that was already working when I try to extend it.

    As I modified spellNumber to handle each new range of inputs, I sometimes adjusted the code I’d already written to make it easier for the new code to use it. Having all the tests helped me make sure I didn’t break the older code in the process.

    Along the way, I made mistakes, and had to figure out how to fix outputs like «thirty-zero» in a way that still allowed for «zero.»

    Style

    Comments and docstrings

    Your comments on what the functions do are useful, but I think the Pythonic way to document a function is to use a docstring. So, instead of:

    def myFunction(): # This is what my function does
    

    Write:

    def myFunction():
      """This is what my function does."""
    

    It’s appropriate to use regular comments for details in your code, but comments that describe how a function (or class or file) is intended to be used should probably be docstrings.

    Cascades of if-statements

    Whenever you have a lot of similarly structured if-statements (if this: blah elif that: blub elif other: ...), consider whether using a data structure would be a better way to represent the problem.

    For example, I used a table for the small numbers.
    Another answer had a good idea of using a dictionary in a similar way. A data structure you can index into or a table you can loop through will also be more efficient than a big cascade of if-statements.

    More importantly, data is easy to modify and extend and greatly reduces the amount «logic» you have to worry about. For me separating the logic from the data, and made it easier to check the spelling of all those words, because they’re all clustered nicely together instead of scattered across several helper functions.

    Example 1, we are going to convert a number to its wording. For instance, if the number is 12, the wordings will be “one-two”. A similar thing will be done for the rest of the inputs.

    Example 1:

    arr = ['zero','one','two','three','four','five','six','seven','eight','nine']
     
    def number_2_word(n):
     
        # If all the digits are encountered return blank string
        if(n==0):
            return ""
         
        else:
            # compute spelling for the last digit
            small_ans = arr[n%10]
     
            # keep computing for the previous digits and add the spelling for the last digit
            ans = number_2_word(int(n/10)) + small_ans + " "
         
        # Return the final answer
        return ans
     
    n = int(input())
    print("Number Entered was : ", n)
    print("In English: ",end="")
    print(number_2_word(n))

    Output:

    Example 2: we are going to convert the number to its digital-place wise. For instance, if the number is 12, then the result will be twelve. Similar thing will be done for rest of the inputs.

    Example 2:

    Pre-defined Input

    # convert a single-digit or two-digit number into words
    def convertToDigit(n, suffix):
     
        # if `n` is zero
        if n == 0:
            return EMPTY
     
        # split `n` if it is more than 19
        if n > 19:
            return Y[n // 10] + X[n % 10] + suffix
        else:
            return X[n] + suffix
     
     
    # convert a given number (max 9-digits) into words
    def convert(n):
        # add digits at ten million and hundred million place
        result = convertToDigit((n // 1000000000) % 100, 'Billion, ')
     
        # add digits at ten million and hundred million place
        result += convertToDigit((n // 10000000) % 100, 'Crore, ')
     
        # add digits at hundred thousand and one million place
        result += convertToDigit(((n // 100000) % 100), 'Lakh, ')
     
        # add digits at thousand and tens thousand place
        result += convertToDigit(((n // 1000) % 100), 'Thousand, ')
     
        # add digit at hundred place
        result += convertToDigit(((n // 100) % 10), 'Hundred ')
     
        if n > 100 and n % 100:
            result += 'and '
     
        # add digits at ones and tens place
        result += convertToDigit((n % 100), '')
     
        return result.strip().rstrip(',').replace(', and', ' and')
     
     
    #convert numbers to words
    if __name__ == '__main__':
        EMPTY = ''
     
        X = [EMPTY, 'One ', 'Two ', 'Three ', 'Four ', 'Five ', 'Six ', 'Seven ',
            'Eight ', 'Nine ', 'Ten ', 'Eleven ', 'Twelve ', 'Thirteen ', 'Fourteen ',
            'Fifteen ', 'Sixteen ', 'Seventeen ', 'Eighteen ', 'Nineteen ']
     
        Y = [EMPTY, EMPTY, 'Twenty ', 'Thirty ', 'Forty ', 'Fifty ',
            'Sixty ', 'Seventy ', 'Eighty ', 'Ninety ']
     
        print(convert(0))
        print(convert(7000))
        print(convert(75432))
        print(convert(997751076))
        print(convert(6147493690))

    Output:

    The Tech Platform

    www.thetechplatform.com

    num2words — библиотека, которая переводит числа (например, 42) в слова (сорок два) или даже в порядковые числительные (сорок второй).

    Очень проста в использовании:

    from num2words import num2words
    
    print(num2words(42))  # Выведет forty-two
    print(num2words(42, to='ordinal')) # Выведет forty-second
    print(num2words(42, lang='fr'))  # Выведет quarante-deux
    

    Помимо основного аргумента-числа есть необязательные, дополнительные аргументы:

    • Аргумент to может принимать следущие значения:

      • "cardinal" — просто перевод в число: 2019 —> two thousand and nineteen.
      • "ordinal" — перевод в порядковое числительное: 2019 —> two thousand and nineteenth.
      • "ordinal_num" — оставить числом: 2019 —> 2019th.
      • "year" — в год: 2019 —> twenty nineteen
      • "currency" — в евро: 2019 —> twenty euro, nineteen cents
    • lang — определяет в какой язык переводить:

      • "en" (English, default)
      • "ar" (Arabic)
      • "cz" (Czech)
      • "de" (German)
      • "dk" (Danish)
      • "en_GB" (English — Great Britain)
      • "en_IN" (English — India)
      • "es" (Spanish)
      • "es_CO" (Spanish — Colombia)
      • "es_VE" (Spanish — Venezuela)
      • "eu" (EURO)
      • "fi" (Finnish)
      • "fr" (French)
      • "fr_CH" (French — Switzerland)
      • "fr_BE" (French — Belgium)
      • "fr_DZ" (French — Algeria)
      • "he" (Hebrew)
      • "id" (Indonesian)
      • "it" (Italian)
      • "ja" (Japanese)
      • "ko" (Korean)
      • "lt" (Lithuanian)
      • "lv" (Latvian)
      • "no" (Norwegian)
      • "pl" (Polish)
      • "pt" (Portuguese)
      • "pt_BR" (Portuguese — Brazilian)
      • "sl" (Slovene)
      • "sr" (Serbian)
      • "ro" (Romanian)
      • "ru" (Russian)
      • "sl" (Slovene)
      • "tr" (Turkish)
      • "th" (Thai)
      • "vi" (Vietnamese)
      • "nl" (Dutch)
      • "uk" (Ukrainian)

    Некоторые коды состоят из языка и страны: fr_FR. Если страна не поддерживается, но поддерживается язык, то программа использует код языка: fr. Если вы используете язык не из этого списка, получите NotImplementedError.


    Попробуйте бесплатные уроки по Python

    Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

    Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

    Набор на курс до мидла

    Набор на курс до мидла

    Понравилась статья? Поделить с друзьями:
  • Converter from excel to pdf скачать бесплатно
  • Converter from djvu to word
  • Converter for pdf to word free download
  • Converter for pdf to excel online converter
  • Converter for pdf to excel file