Python fractions module
As we know, a fraction is a number which represents a whole number being divided into multiple parts. Python fractions module allows us to manage fractions in our Python programs.
Managing fractions
In this Python post, we will manage fractions and perform various operations on them. Let’s get started.
Creating Fractions
Fraction class in Python allows us to make its instance in various ways. Here is a sample program:
1 2 3 4 5 6 |
import fractions for num, decimal in [(3, 2), (2, 5), (30, 4)]: fract = fractions.Fraction(num, decimal) print('{}/{} = {}'.format(num, decimal, fract)) |
Let’s see the output for this program:
This means that we can easily convert a fraction into a String and manage it to debug in our prograns. Also, notice that in the last fraction 30/4
, it was automatically resolved to the lowest form as 15/2
.
We can also create a fraction from its String representation actually, like:
1 2 3 |
f = fractions.Fraction('2/7') |
Converting Decimals to Fractions
It is also possible to convert a decimal into a Fractional number. Let’s look at a code snippet:
1 2 3 4 5 6 |
import fractions for deci in ['0.6', '2.5', '2.3', '4e-1']: fract = fractions.Fraction(deci) print('{0:>4} = {1}'.format(deci, fract)) |
Let’s see the output for this program:
Pretty easy to manage, right? But here is a catch, decimal values which cannot be exactly turned into a fraction might yield unexpected results like:
1 2 3 4 5 |
import fractions for v in [0.1, 0.5, 1.5, 2.0]: print('{} = {}'.format(v, fractions.Fraction(v))) |
This will give an output as:
Noticed the issue with 0.1
representation? Let’s understand why this happens.
Issue with 0.1 representation
As we clearly know, floats consist of two parts, an integer and an exponent part of which the base is taken to and multiplied by the integer part.
Base 10
makes working with math very easy as with Base 10, every number can be presented very easily. 0.5
can be represented as 5 x 10?¹
. So, if we add numbers like 0.5 and 0.2, the result will be 0.7. But, the computers don’t work that way. Computers use Base 2 and not Base 10.
The issue arises with numbers which can be represented by Base 10 but not Base 2. Those numbers have to be rounded off to their closest equivalent. Considering the IEEE 64-bit floating point format, the closest number to 0.1 is 3602879701896397 x 2???
, and the closest number to 0.2 is 7205759403792794 x 2???
; adding them gives 10808639105689191 x 2???
, or an exact decimal value of 0.3000000000000000444089209850062616169452667236328125
. Floating point numbers are generally rounded for display.
Arithmetic Operations
We can also perform Arithmetic Operations quite easily with fractional numbers. Let’s see some examples here.
Performing Mathematical operations
Let’s construct a simple example that shows how to perform arithmetic operations with fractional numbers. Here is a sample program:
1 2 3 4 5 6 7 8 9 |
import fractions f_one = fractions.Fraction(3, 5) f_two = fractions.Fraction(4, 9) print('{} + {} = {}'.format(f_one, f_two, f_one + f_two)) print('{} - {} = {}'.format(f_one, f_two, f_one - f_two)) print('{} * {} = {}'.format(f_one, f_two, f_one * f_two)) print('{} / {} = {}'.format(f_one, f_two, f_one / f_two)) |
Let’s see the output for this program:
Getting parts of fractions
It is possible to get only the numerator or the denominator of a fraction. Let’s look at a code snippet on how this can be done:
1 2 3 4 5 6 |
import fractions fract = fractions.Fraction(221, 234) + fractions.Fraction(1, 2) print("Numerator: {}".format(fract.numerator)) print("Denominator: {}".format(fract.denominator)) |
Let’s see the output for this program:
Making Approximations
We can use the fractions module to approximate and round off a number to a rational value. Here is a sample program:
1 2 3 4 5 6 7 8 9 10 |
import fractions import math print('Value of PI: {}'.format(math.pi)) pi_fraction = fractions.Fraction(str(math.pi)) print('Without limit: {}'.format(pi_fraction)) for num in [1, 6, 11, 60, 70, 90, 100]: limited = pi_fraction.limit_denominator(num) print('{0:8} = {1}'.format(num, limited)) |
Let’s see the output for this program:
The limit_denominator()
function finds and returns the closest fraction that has the denominator with maximum value of num
passed to it.
Rounding off fractions
It is possible to round off fractions by the number of digits we want in the denominator. Let’s look at a code snippet:
1 2 3 4 5 6 7 |
import fractions fract = fractions.Fraction('25/3') print('25/3 Rounded without limit : {}'.format(round(fract))) print('25/3 Rounded to 1 digit : {}'.format(round(fract, 1))) print('25/3 Rounded to 2 digits : {}'.format(round(fract, 2))) |
Let’s see the output for this program:
Note that round()
is a default Python’s interpreter function and doesn’t want any imports.
Mixing Math with Fractions
In a final example, we will bring some functions from math library and mix them with fractional representations here. Like flooring a fraction etc. Let’s look at a code snippet:
1 2 3 4 5 6 7 8 9 |
import math from fractions import Fraction print("25/2 Square root is: {}".format(math.sqrt(Fraction(25, 4)))) print("28/3 Square root is: {}".format(math.sqrt(Fraction(28,3)))) print("4102/1193 Floored to: {}".format(math.floor(Fraction(4102, 1193)))) print("Pi/3 Sined Fraction: {}".format(Fraction(math.sin(math.pi/3)))) print("Pi/3 Sined Fraction Limit Dn.: {}".format(Fraction(math.sin(math.pi/3)).limit_denominator(10))) |
Let’s see the output for this program:
The floor() function just rounds of a decimal equivalent and provides the nearest integer.
Conclusion
In this lesson, we studied how we can manage and use Fraction values in our Python program effectively.
Reference: API Doc