JustToThePoint English Website Version
JustToThePoint en español
JustToThePoint in Thai

Fractions in Python

Five out of four people have trouble with fractions, Steven Wright.

A fraction is a fancy way of representing the division of a whole into parts, for example, half of a pizza (1⁄2), a quarter of an apple (1⁄4), etc.

Fraction module in Python

The fractions module provides support for rational number arithmetic. We can create fractions from integers, floats, decimals, and strings.

Hi@Welcome:~ python
Python 3.8.6 (default, May 27 2021, 13:28:02) 
>>> from fractions import Fraction # Firstly, we need to import the fractions module.
>>> print(Fraction()) # A fraction is formed by a pair of integers as numerator and denominator. The default values for the numerator and denominator are 1 and 0 respectively. 
0
>>> print(Fraction(0.25)) # The class Fraction accepts floating point numbers as arguments. 
1/4
>>> print(Fraction(8, 20)) # It creates a new fraction and it will be automatically normalized, i.e., it calculates the irreducible fraction.
2/5
>>> print(Fraction(6, 14))
3/7
>>> import math
>>> print (math.gcd(8, 20)) # The Highest Common Factor (gcd) can be obtained in Python using a single function offered by the math module. 
4

820 = 8: gcd(8,20)20: gcd(8, 20) = 8: 420: 4= 25

>>> print (math.gcd(6, 14))
2
>>> print(Fraction(2, 0))
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.10/fractions.py", line 156, in __new__
    raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
ZeroDivisionError: Fraction(2, 0)

Fraction raises a ZeroDivisionError exception when the argument passed as denominator is 0.

>>> print(Fraction("7/8"))
7/8
>>> print(Fraction(0.75))
3/4
>>> print(Fraction(2.3))
2589569785738035/1125899906842624

What’s going on? In base 10 which you’re likely to be comfortable with, you can’t express 1/3 exactly. It’s 0.3333333… (recurring). The same goes with 2.3 in base 2 = 10.0100110011001100110011001100110011001100110011001100110011…2. In other words, some decimal numbers cannot be represented exactly in binary.

>>> (2.3).as_integer_ratio() 
# Returns a pair of integers whose ratio is exactly equal to the original float and with a positive denominator. 

(2589569785738035, 1125899906842624)

Operations on Rational Numbers

>>> Fraction(2, 3) + Fraction(4, 5) # Doing arithmetic with rational numbers is as easy as pie.
Fraction(22, 15)
>>> Fraction(2, 3) + 5
Fraction(17, 3)
>>> Fraction(2, 3) + 5 -0.2
5.466666666666667 
>>> Fraction(2, 3) - Fraction(4, 5)
Fraction(-2, 15)
>>> Fraction(2, 3) - 5
Fraction(-13, 3)
>>> Fraction(2, 3) * Fraction(4, 5)
Fraction(8, 15)
>>> Fraction(2, 3) * 7
Fraction(14, 3)
>>> Fraction(2, 3) / Fraction(4, 5)
Fraction(5, 6)
>>> Fraction(2, 3) / 7
Fraction(2, 21)
>>> Fraction(2, 3)**2 
We can raise fractions to a power, (23)2 = 49.
Fraction(4, 9)
>>> Fraction(2, 3) < Fraction(4, 5) # We can see how Python's comparison operators work on fractions.
True
>>> Fraction(2, 3) > 5.2
False

Writing a Fraction Class

# It is necessary to overload 
from __future__ import division

def gcd(a, b):
    """ It returns the greatest common divisor of a and b."""
    while b:
        a, b = b, a % b
    return a

class Fraction:
    ## A Fraction instance is constructed from a pair of integers.
    # @param n is the numerator of the fraction (default is 0) 
    # @param d is the denominator of the fraction (default is 1)
    def __init__(self, n = 0, d = 1):
        if (not isinstance(n, int)):
            raise TypeError("The numerator of a Fraction must be an integer")
        if (not isinstance(d, int)):
            raise TypeError("The denominator of a Fraction must be an integer")
        
        self.numerator = int(n / gcd(abs(n), abs(d))) 
        # It creates a new fraction and it will be automatically normalized, i.e., it calculates the irreducible fraction. 
        # print(Fraction(8, 20)) returns 2/5.
        self.denominator = int(d / gcd(abs(n), abs(d)))
        if self.denominator < 0:
            self.denominator = abs(self.denominator)
            self.numerator = -1*self.numerator
        # The denominator cannot be zero, so it raises a ZeroDivisionError if denominator = 0.
        elif self.denominator == 0:
            raise ZeroDivisionError("Denominator cannot be zero")
    
    @classmethod
    def from_string(cls, text):
        """ It generates a Fraction object from a string representation of two integers separated by '/'. 
        >> print(Fraction.from_string('4/9')) return 4/9. Credits: jonrsharpe, codereview.stackexchange.com"""
        return cls(*[int(i) for i in text.split('/')])

    ## It implements the addition of two fractions.
    # @params other is the fraction from which self is to be added.
    # @return the new Fraction object that is the result of self + other.
    def __add__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        num = self.numerator * other.denominator + self.denominator * other.numerator
        den = self.denominator * other.denominator
        return Fraction (num, den)
    
    __radd__ = __add__

radd is called if the left object does not have an add method or that method does not know how to add the two objects, e.g., f1 = Fraction(1, 3), print(2 + f1).

    ## It implements the subtraction of two fractions.
    # @params other is the fraction from which self is to be subtracted.
    # @return the new Fraction object that is the result of self - other.
    def __sub__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        num = self.numerator * other.denominator - self.denominator * other.numerator
        den = self.denominator * other.denominator
        return Fraction (num, den)

    def __rsub__(self, other):
        return Fraction(other) - self

    ## It determines if this fraction is equal to another fraction.
    # @params other is the right-hand side fraction.
    # @return True if both fractions (self and other) are equal. Otherwise, it returns False. 
    def __eq__(self, other):
        return (self.numerator == other.numerator and self.denominator == other.denominator)
     
    def __lt__(self, other):
        # We can implement the __lt__ method by putting self and other in common terms and then comparing the numerators.
        return (self.numerator * other.denominator < self.denominator * other.numerator)

    def __ne__(self, other):
        return not self == other

    def __le__(self, other):
        return self < other or self == other

    def __gt__(self, other):
        return other < self

    def __ge__(self, other): 
        return self > other or self == other

    ## It implements the multiplication of two fractions.
    # @params other is the fraction from which self is to be multiplied.
    # @return the new Fraction object that is the result of self multiplied by other. 
    def __mul__(self, other): 
        if isinstance(other, int):
            other = Fraction(other)
        return Fraction(self.numerator * other.numerator, self.denominator * other.denominator)
    
    __rmul__ = __mul__
    
    ## It implements the division of two fractions.
    # @params other is the fraction from which self is to be divided.
    # @return the new Fraction object that is the result of self divided by other.
    def __truediv__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        return Fraction(self.numerator * other.denominator, self.denominator * other.numerator)
    
    def __rtruediv__(self, other):
        return Fraction(other)/self

    def __float__(self):
        return self.numerator / self.denominator
    
    ## It converts the object into a string.
    # @return a string in the format numerator/denominator. If the object represents an improper function (it has a numerator that is greater 
    # than the denominator), it returns the fraction as a mixed fraction written as the sum of a whole number and a proper fraction. 
    def __str__(self):
        if self.denominator == 1:
            return str(self.numerator)
        elif abs(self.numerator) > self.denominator:
            if self.numerator > 0:
                a = self.numerator // self.denominator
                b = self.numerator % self.denominator
                return "{} {}/{}".format(a, b, self.denominator)
            else:
                a = - (abs(self.numerator) // self.denominator)
                b = - (abs(self.numerator) % self.denominator)
                return "{} {}/{}".format(a, -b, self.denominator)

        else:
            return str(self.numerator) + "/" + str(self.denominator)
def main():
    print(Fraction(2, -1)) # -2                  
    print(Fraction(8, 20)) # 2/5
    print(Fraction(5, 4)) # 1 1/4
    print(Fraction.from_string('4/9')) # 4/9
    f0 = Fraction.from_string('3/4')
    print(2+f0) # 2 3/4
    print(2-f0) # 1 1/4
    print(2*f0) # 1 1/2
    print(2/f0) # 2 2/3
    f1 = Fraction(5, 3)
    f2 = Fraction(3, -4)

    try:
        f3 = Fraction(3, 0)
    except ZeroDivisionError:
        print("Oops! Denominator cannot be zero")

    f3 = f1 + f2
    print(f1, "+", f2, "=", f3) # 1 2/3 + -3/4 = 11/12
    f3 = f1 - f2
    print(f1, "-", f2, "=", f3) # 1 2/3 - -3/4 = 2 5/12
    f3 = f1 * f2
    print(f1, "*", f2, "=", f3) # 1 2/3 * -3/4 = -1 1/4
    f3 = f1 / f2
    print(f1, "/", f2, "=", f3) 1 2/3 / -3/4 = -2 2/9
    f3 = Fraction(4, 6)
    print("Is", f3, " = ", f1, "?=", f3 == f1) # Is 2/3  =  1 2/3 ?= False
    print("Is", f3, " < ", f1, "?=", f3 < f1) # Is 2/3  <  1 2/3 ?= True
    print("Is", f3, " >= ", f2, "?=", f3 >= f2) # Is 2/3  >=  -3/4 ?= True
    print("Is", f3, " != ", f2, "?=", f3 != f2) # Is 2/3  !=  -3/4 ?= True
    print(f3, "=", "{:.2f}".format(round(float(f3), 2)), "=",  round(float(f3)*100, 2), "%") # 2/3 = 0.67 = 66.67 %
    f4 = Fraction(1, 3)
    print(f4, "=", "{:.2f}".format(round(float(f4), 2)), "=",  round(float(f4)*100, 2), "%") # 1/3 = 0.33 = 33.33 %
if __name__ == '__main__':
    main()
Bitcoin donation

JustToThePoint Copyright © 2011 - 2024 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.