# bestfraction.py # Walker M. White (wmw2) # October 7, 2012 """Module with a simple Fraction class. This module shows off operator overloading. This allows us to define complex mathematical objects. This version of Fraction has getters and setters, which allow us to enforce our invariants. This is the prefered way to make a class in Python""" import math def gcd(a,b): """Returns: Greatest common divisor of x and y. Precondition: x and y are integers.""" assert type(a) == int,`x`+' is not an int' assert type(b) == int,`y`+' is not an int' while b != 0: t = b b = a % b a = t return a class Fraction(object): """Instance is a fraction n/d INSTANCE ATTRIBUTES: _numerator [int]: top _denominator [int > 0]: bottom""" # GETTERS AND SETTERS def getNumerator(self): """Returns: fraction numerator.""" return self._numerator # returns the field def setNumerator(self,value): """Sets the numerator as value Preccndition: value is an int.""" # enforce invariant assert type(value) == int, `value`+' is not an int' # assign to field self._numerator = value def getDenominator(self): """Returns: fraction denominator.""" return self._denominator # returns the field def setDenominator(self,value): """Sets the denominator as value. Precondition: value is an int > 0""" # enforce invariant assert type(value) == int, `value`+' is not an int' assert value > 0, `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 Precondition: n an int, d > 0 an int.""" # No need for asserts; setters handle everything self.setNumerator(n) self.setDenominator(d) # OPERATORS def __str__(self): """Returns: this Fraction as a string 'n/d'""" return str(self.getNumerator())+'/'+str(self.getDenominator()) def __repr__(self): """Returns: unambiguous representation of Fraction""" return str(self.__class__)+'['+str(self)+']' def __mul__(self,other): """Returns: Product of self and other as a new Fraction Does not modify contents of self or other Precondition: other is a Fraction""" assert isinstance(other, Fraction) top = self.getNumerator()*other.getNumerator() bot = self.getDenominator()*other.getDenominator() return Fraction(top,bot) def __add__(self,other): """Returns: Sum of self and other as a new Fraction Does not modify contents of self or other Precondition: other is a Fraction""" assert isinstance(other, Fraction) bot = self.getDenominator()*other.getDenominator() top = (self.getNumerator()*other.getDenominator()+ self.getDenominator()*other.getNumerator()) return Fraction(top,bot) def __eq__(self,other): """Returns: True if self, other are equal Fractions. False if not equal, or other not a Fraction""" if not isinstance(other, Fraction): return False # Cross multiply left = self.getNumerator()*other.getDenominator() rght = self.getDenominator()*other.getNumerator() return left == rght def __ne__(self,other): """Returns: False if self, other are equal Fractions. True if not equal, or other not a Fraction""" return not self == other def __cmp__(self,other): """Returns: a negative integer if self < other, zero if self == other, a positive integer if self > other Used to implement comparison operations. Precondition: other is a Fraction.""" assert isinstance(other, Fraction) # Cross multiply left = self.getNumerator()*other.getDenominator() rght = self.getDenominator()*other.getNumerator() return left - rght # NORMAL METHODS def reduce(self): """Normalizes this fraction so that numerator and denominator have no common divisors.""" g = gcd(self.getNumerator(),self.getDenominator()) self.setNumerator(self.getNumerator()/g) self.setDenominator(self.getDenominator()/g)