# newfraction.py # Walker M. White (wmw2) # October 7, 2012 """Module with a simple Fraction class. This module shows off dispatch on type for add and multiply.""" 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: Makes 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 or an int""" assert isinstance(other, Fraction) or type(other) == int if type(other) == int: return self._multiplyInt(other) return self._multiplyFraction(other) # Private helper to multiply fractions def _multiplyFraction(self,other): # No need to enforce preconditions on a hidden method top = self.getNumerator()*other.getNumerator() bot = self.getDenominator()*other.getDenominator() return Fraction(top,bot) # Private helper to multiply ints def _multiplyInt(self,x): # No need to enforce preconditions on a hidden method top = self.getNumerator()*x bot = self.getDenominator() return Fraction(top,bot) def __rmul__(self,other): """Returns: Product of self and other as a new Fraction This method allows us to put the int on the left. Precondition: other is a Fraction""" assert isinstance(other, Fraction) or type(other) == int if type(other) == int: return self._multiplyInt(other) return self._multiplyFraction(other) 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) or type(other) == int if type(other) == int: return self._addInt(other) return self._addFraction(other) # Private helper to multiply fractions def _addFraction(self,other): # No need to enforce preconditions on a hidden method bot = self.getDenominator()*other.getDenominator() top = (self.getNumerator()*other.getDenominator()+ self.getDenominator()*other.getNumerator()) return Fraction(top,bot) # Private helper to multiply ints def _addInt(self,x): # No need to enforce preconditions on a hidden method bot = self.getDenominator() top = (self.getNumerator()+self.getDenominator()*x) return Fraction(top,bot) def __radd__(self,other): """Returns: Sum of self and other as a new Fraction This method allows us to put the int on the left. Precondition: other is a Fraction""" assert isinstance(other, Fraction) or type(other) == int if type(other) == int: return self._addInt(other) return self._addFraction(other) 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) and type(other) != int: return False if type(other) == int: return self.getNumerator() == other*self.getDenominator() # 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.""" if not isinstance(other, Fraction) and type(other) != int: return False if type(other) == int: return self.getNumerator() - other*self.getDenominator() # 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)