# betterfraction.py # Walker M. White (wmw2) # October 7, 2015 """Module with a simple Fraction class. This module shows off operator overloading. This allows us to define complex mathematical objects. This version of Fraction uses getters and setters. This allows us to enforce our invariants, but is very unwieldy. Notice the use of get and set methods EVERYWHERE.""" 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] _denominator: [int > 0]""" # GET AND SET METHODS def getNumerator(self): """Returns: Fraction numerator.""" return self._numerator # returns the field 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, `value`+' is not an int' # assign to field self._numerator = value def getDenominator(self): """Fraction denominator. Invariant: Must be an int > 0.""" return self._denominator # returns the field 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, `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 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 (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 str(self.getNumerator())+'/'+str(self.getDenominator()) def __repr__(self): """Returns: The unambiguous representation of Fraction""" return str(self.__class__)+'['+str(self)+']' def __mul__(self,other): """Returns: 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: 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) 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 top = self.getNumerator()*other.getNumerator() bot = self.getDenominator()*other.getDenominator() return left == rght def __ne__(self,other): """Returns: False if self, other are equal Fractions. It returns True if they are not equal, or other is not a Fraction Parameter other: value to compare to this fraction Precondition: NONE""" return not self == other def __cmp__(self,other): """Returns: whether self < other, self == other, or self > other This method returns an integer. The value is negative is self < other. The value is zero if self == other. Finally, the value is positive if self > other. The actual value returned does not matter and is not specified. This method is used to implement all comparison operations. Parameter other: value to compare to this fraction Precondition: other is a Fraction""" assert type(other) == Fraction # Cross multiply top = self.getNumerator()*other.getNumerator() bot = self.getDenominator()*other.getDenominator() return left - rght 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)