 Python

# How to Use the Decimal Module in Python

This article will cover a guide on using the “Decimal” module in Python. It can be used to run various mathematical operations on floating point numbers or numbers containing decimals points. All code samples in this article are tested with Python 3.9.5 on Ubuntu 21.04.

The decimal module, as the name suggests, can be used to handle numbers having decimal points or floating type numbers. The methods included in this module help in rounding off decimal numbers, convert numbers and perform arithmetic calculations. It also focuses a lot on precision and accuracy and each number after a decimal point is considered significant. The decimal module considers a number like 1.40 as 1.40 and not as 1.4. The usage of the decimal module can be best understood through examples. Some of them are explained below.

## Performing Basic Mathematical Calculations using the Decimal Module

You can call the Decimal constructor to convert a number to a decimal type in Python. The code sample below shows the difference between basic mathematical division done on integer type numbers and decimal type numbers.

from decimal import Decimal

a = 10
b = 11
c = a / b
d = Decimal(a) / Decimal(b)
print (c, type(c))
print (d, type(d))

The first statement imports the Decimal class from the decimal module. Next, two variables “a” and “b” are created with some values. The variable “c” stores a value produced by dividing the variable a by b. The same process is then repeated by converting the numbers to decimal type objects. After running the above code sample, you should get the following output:

0.9090909090909091 <class 'float'>
0.9090909090909090909090909091 <class 'decimal.Decimal'>

As you can see in the output above, the float type object shows numbers with less precision than the decimal type object as it uses a much more aggressive approximation method than the decimal type object. By default, a decimal type number in Python shows upto 28 numbers. You can change this value according to your need by calling the “getcontext” method available in the decimal module.

from decimal import Decimal
from decimal import getcontext

getcontext().prec = 50
a = 10
b = 11
c = a / b
d = Decimal(a) / Decimal(b)
print (c, type(c))
print (d, type(d))

In the code sample above, the getcontext function has been imported and the precision position has been set to upto 50 positions. The getcontext method can be used to view the current context in the thread and change some of the default configuration parameters for the decimal module. After running the above code sample, you should get the following output:

0.9090909090909091 <class 'float'>
0.90909090909090909090909090909090909090909090909091 <class 'decimal.Decimal'>

You can perform any type of arithmetic calculations with decimal type objects that you can perform with float type objects in Python. The large number of trailing decimal numbers in decimal type objects can bring pinpoint accurate numbers that are especially useful in financial, accounting, mission critical scientific applications, and so on.

Note that you can create decimal type numbers from floats, integers, and strings containing numbers by calling the main Decimal constructor.

## Rounding Off Numbers using the Decimal Module

The decimal module comes with some predefined rounding modes that you can use to round off numbers with decimal points. These modes are called ROUND_FLOOR, ROUND_CEILING, ROUND_HALF_DOWN, ROUND_HALF_UP, ROUND_UP, ROUND_DOWN, ROUND_HALF_EVEN, and ROUND_05UP. According to the official Python documentation, here is what each of these modes do:

• ROUND_FLOOR: Number is rounded towards negative infinity.
• ROUND_CEILING: Number is rounded towards infinity or positive infinity.
• ROUND_HALF_DOWN: Numbers are rounded to the nearest number. If there is a tie, the number is rounded towards zero. Ties are equidistant numbers that can be rounded both up or down. For instance a number like 4.25 can be rounded towards both 4.2 and 4.3.
• ROUND_HALF_UP: Numbers are rounded to the nearest number. If there is a tie, the number is rounded away from zero.
• ROUND_UP: Number is rounded away from zero.
• ROUND_DOWN: Number is rounded towards zero.
• ROUND_HALF_EVEN: Numbers are rounded to the nearest number. Any ties are rounded to the nearest even integer.
• ROUND_05UP: Numbers are rounded away from zero if the last number is either 0 or 5. If not, then numbers are rounded towards zero.

The code sample below shows the behavior of these modes.

import decimal
from decimal import Decimal
from decimal import getcontext

getcontext().prec = 2

getcontext().rounding = decimal.ROUND_FLOOR
print (Decimal(3.961) + Decimal(0))

getcontext().rounding = decimal.ROUND_CEILING
print (Decimal(3.961) + Decimal(0))

getcontext().rounding = decimal.ROUND_HALF_DOWN
print (Decimal(3.705) + Decimal(0))

getcontext().rounding = decimal.ROUND_HALF_UP
print (Decimal(3.775) + Decimal(0))

getcontext().rounding = decimal.ROUND_UP
print (Decimal(3.775) + Decimal(0))

getcontext().rounding = decimal.ROUND_DOWN
print (Decimal(3.609) + Decimal(0))

getcontext().rounding = decimal.ROUND_HALF_EVEN
print (Decimal(3.665) + Decimal(0))

getcontext().rounding = decimal.ROUND_05UP
print (Decimal(3.675) + Decimal(0))

The code sample is pretty straight forward. A precision of 2 digits is set for rounding off the numbers. The rounding method is changed by setting the value of the “rounding” object (part of the main context). After running the above code sample, you should get the following output where each line corresponds to the respective rounding mode:

3.9
4.0
3.7
3.8
3.8
3.6
3.7
3.6

## Rounding Off using the Quantize Method

You can also use the “quantize” method available in the decimal module to round off the numbers. The process is identical to the method explained above. However, instead of setting precision numbers separately, you can supply an exponent as an argument to the quantize method to round off a number to a particular position. Below is a code sample.

import decimal
from decimal import Decimal

rounded = Decimal(3.961).quantize(Decimal('1.0'), rounding=decimal.ROUND_FLOOR)
print (rounded)

An exponent of ‘1.0’ has been supplied to the quantize method and a rounding method has been supplied as an extra argument. It will return a number in X.X format. After running the above code sample, you should get the following output:

3.9

## Comparing Two Decimal Numbers

You can compare any two decimal type objects using the “compare” method available in the decimal module. The examples below show its usage.

from decimal import Decimal

print (Decimal(1.2).compare(Decimal(1.1)))
print (Decimal(1.0).compare(Decimal(1.1)))
print (Decimal(1.0).compare(Decimal(1.0)))

You can call the compare method on a decimal type object and supply the other number as an argument. A value of 0, 1, or -1 will be returned depending on the numbers being compared. A value of 0 indicates both numbers being equal, a value of 1 indicates the first number being greater than the second number, and a value of -1 indicates that the first number is less than the second number.  After running the above code sample, you should get the following output:

1
-1
0

## Conclusion

Though the decimal module is most commonly used to control decimal precision and to round off numbers after the decimal point, it comes with some other useful methods that can be further used to manipulate decimal numbers to produce accurate results from arithmetic calculations. The basic usage of the decimal module has been covered in this article and it should be enough for most situations. But you can always read more about the advanced methods from the official Python documentation. 