47. Fractions - part 4

As you should have checked at the end of the previous lesson, Python does not know how to add an integer to a Fraction. We can correct that easily enough by doing the following:

  1. Before doing a mathematical operation [+, *, /, -], check to see if the "other" object is a Fraction, if not convert it before doing the operation.
  2. Tell Python how to convert integers to Fractions.

The second step can be accomplished with a function like the following:

def convertToFraction(object):
    '''Converts "int" and "long" to Fractions'''
    if type(object) in (int, long):
        return Fraction(object)
    else:
        raise NotImplementedError

We first check if the object is an integer [int or perhaps long] and, if so, create a new Fraction from it (the integer will be the numerator of the new Fraction). Since we want fractions to be of the form (integer/integer), we will not allow any other kind of object; by raising an exception, we inform the user that the attempted operation is not permitted.

The first step will be something that we will add at the beginning of every operation. Here's the new code that does just that. [Note that we included the conversion to Fractions as a method of that class.]

  1 def gcd(a, b):
  2     '''gcd returns the greatest common divisor 
  3         of given 2 integers.'''
  4     while b:
  5         a, b = b, a%b
  6     return a
  7 
  8 class Fraction(object):
  9     def __init__(self, numerator, denominator=1):
 10         num, denom = self.simplify(numerator, denominator)
 11         self.num = num
 12         self.denom = denom
 13         
 14     def __str__(self):
 15         if self.denom == 1:
 16             return "(%s)"%self.num
 17         return "(%s/%s)"%(self.num, self.denom)
 18 
 19     def __mul__(self, other):
 20         if not type(other) == Fraction:
 21             other = self.convertToFraction(other)
 22         num = self.num * other.num
 23         denom = self.denom * other.denom
 24         return Fraction(num, denom)
 25 
 26     def __div__(self, other):
 27         if not type(other) == Fraction:
 28             other = self.convertToFraction(other)
 29         num = self.num * other.denom
 30         denom = self.denom * other.num
 31         return Fraction(num, denom)
 32 
 33     def __add__(self, other):
 34         if not type(other) == Fraction:
 35             other = self.convertToFraction(other)
 36         denom = self.denom * other.denom
 37         num = self.num*other.denom + self.denom*other.num
 38         return Fraction(num, denom)
 39 
 40     def __sub__(self, other):
 41         if not type(other) == Fraction:
 42             other = self.convertToFraction(other)
 43         denom = self.denom * other.denom
 44         num = self.num*other.denom - self.denom*other.num
 45         return Fraction(num, denom)
 46 
 47     def simplify(self, a, b):
 48         '''divides two integers by their common factor.'''
 49         common_factor = gcd(a, b)
 50         a /= common_factor
 51         b /= common_factor
 52         return a, b
 53 
 54     def convertToFraction(self, object):
 55         '''Converts "int" and "long" to Fractions'''
 56         if type(object) in (int, long):
 57             return Fraction(object)
 58         else:
 59             raise NotImplementedError
 60 
 61 #== testing area below===
 62 
 63 if __name__ == "__main__":
 64     a = Fraction(1, 2)
 65     b = Fraction(3, 1)
 66     assert str(a) == "(1/2)"
 67     assert str(b) == "(3)"
 68     assert str(a*b) == "(3/2)"
 69     c = Fraction(1, 3)
 70     assert str(b*c) == "(1)"
 71     d = Fraction(5, 10)
 72     assert str(d) == "(1/2)"
 73     assert str(a/b) == "(1/6)"
 74     assert str(a/a) == "(1)"
 75     assert str(a+a) == "(1)"
 76     assert str(b+b) == "(6)"
 77     assert str(a+b) == "(7/2)"
 78     assert str(c+c) == "(2/3)"
 79     assert str(a-a) == "(0)"
 80     assert str(a-b) == "(-5/2)"
 81     assert str(a-c) == "(1/6)"
 82     assert str(a+1) == "(3/2)"
 83     assert str(a*2) == "(1)"
 84     assert str(b-1) == "(2)"
 85     assert str(b/3) == "(1)"

1 + 1 = ?

If you think we are done, try the following:

one = Fraction(1)
print 1 + one

Can you think of what make this go wrong?

previousFractions Part 3 - home - Beyond Python next