""" A module with a simple Fraction class. This module shows off operator overloading. This allows us to define complex mathematical objects. Author: Walker M. White (wmw2) Date: October 20, 2017 (Python 3 Version) """ def gcd(a,b): """ Returns: Greatest common divisor of x and y. Precondition: x and y are integers. """ assert type(a) == int,repr(x)+' is not an int' assert type(b) == int,repr(y)+' is not an int' while b != 0: t = b b = a % b a = t return a class Fraction(object): """ A class to represent a fraction n/d INSTANCE ATTRIBUTES (hidden): numerator: The fraction numerator [int] denominator: The fraction denomenator [int > 0] """ # GETTER AND SETTERS def getNumerator(self): """ Returns: The fraction numerator. """ return self._numerator # returns the attribute def setNumerator(self,value): """ Sets the numerator to value. Parameter value: the new numerator Precondition: value is an int """ # enforce invariant assert type(value) == int, repr(value)+' is not an int' # assign to attribute self._numerator = value def getDenominator(self): """ Returns: The fraction denominator. """ return self._denominator # returns the attribute def setDenominator(self,value): """ Sets the numerator to value. Parameter value: the new denominator Precondition: value is an int > 0 """ # enforce invariant assert type(value) == int, repr(value)+' is not an int' assert value > 0, repr(value)+' is not positive' # assign to field self._denominator = value # INITIALIZER def __init__(self,n=0,d=1): """ Initializer: Creates a new Fraction n/d Parameter n: the numerator (default is 0) Precondition: n is an int (or optional) Parameter d: the denomenator (default is 1) Precondition: d is an int > 0 (or optional) """ # No need for asserts; setters handle everything self.setNumerator(n) self.setDenominator(d) def __str__(self): """ Returns: this Fraction as a string 'n/d' """ return repr(self._numerator)+'/'+repr(self._denominator) def __repr__(self): """ Returns: The unambiguous representation of Fraction """ return str(self.__class__)+'['+str(self)+']' # MATH METHODS def __mul__(self,other): """ Returns: The product of self and other as a new Fraction This method does not modify the contents of self or other Parameter other: the fraction to multiply on the right Precondition: other is a Fraction """ assert type(other) == Fraction top = self.getNumerator()*other.getNumerator() bot = self.getDenominator()*other.getDenominator() return Fraction(top,bot) def __add__(self,other): """ Returns: The sum of self and other as a new Fraction This method does not modify the contents of self or other Parameter other: the fraction to add on the right Precondition: other is a Fraction """ assert type(other) == Fraction bot = self.getDenominator()*other.getDenominator() top = (self.getNumerator()*other.getDenominator()+ self.getDenominator()*other.getNumerator()) return Fraction(top,bot) # COMPARISONS def __eq__(self,other): """ Returns: True if self, other are equal Fractions. It returns False if they are not equal, or other is not a Fraction Parameter other: value to compare to this fraction Precondition: NONE """ if type(other) != Fraction: return False # Cross multiply left = self.getNumerator()*other.getDenominator() rght = self.getDenominator()*other.getNumerator() return left == rght def __lt__(self,other): """ Returns: True if self < other, False otherwise This method is used to implement all strict comparison operations. Both < and > are determined automatically from this method. Parameter other: value to compare to this fraction Precondition: other is a Fraction """ assert type(other) == Fraction # Cross multiply left = self.getNumerator()*other.getDenominator() rght = self.getDenominator()*other.getNumerator() return left < rght def __le__(self,other): """ Returns: True if self < other, False otherwise This method is used to implement all inclusive comparison operations. Both <= and >= are determined automatically from this method. Parameter other: value to compare to this fraction Precondition: other is a Fraction """ assert type(other) == Fraction # Cross multiply left = self.getNumerator()*other.getDenominator() rght = self.getDenominator()*other.getNumerator() return left <= rght # OTHER METHODS def reduce(self): """ Normalizes this fraction into simplest form. Normalization ensures that the numerator and denominator have no common divisors. """ g = gcd(self.getNumerator(),self.getDenominator()) self.setNumerator(self.getNumerator()//g) self.setDenominator(self.getDenominator()//g)