# -*- coding: utf-8 -*- """CMPSC132 - Homework 1.ipynb I have included that code snippets for the PSADS book below. You need to extend the code in order to meet the criteria listed at the end of the chapter. """ def gcd(m, n): while m % n != 0: m, n = n, m % n return n def chk_frac(frac): try: onum = frac.num oden = frac.den except AttributeError: onum = frac oden = 1 return onum, oden class Fraction: def __init__(self, top, bottom): if (type(top) is not int) or (type(bottom) is not int): raise TypeError if bottom < 0: bottom *= -1 top *= -1 cmmn = gcd(top, bottom) self.num = top // cmmn self.den = bottom // cmmn def __str__(self): return "{:d}/{:d}".format(self.num, self.den) def __eq__(self, other_fraction): first_num = self.num * other_fraction.den second_num = other_fraction.num * self.den return first_num == second_num def __add__(self, other_fraction): onum, oden = chk_frac(other_fraction) new_num = self.num * oden \ + self.den * onum new_den = self.den * oden return Fraction(new_num, new_den) def __sub__(self, other_fraction): onum, oden = chk_frac(other_fraction) new_num = self.num * oden \ - self.den * onum new_den = self.den * oden return Fraction(new_num, new_den) def __mul__(self, other_fraction): onum, oden = chk_frac(other_fraction) new_num = self.num * onum new_den = self.den * oden return Fraction(new_num, new_den) def __truediv__(self, other_fraction): onum, oden = chk_frac(other_fraction) new_num = self.num * oden new_den = self.den * onum return Fraction(new_num, new_den) def __gt__(self, other_fraction): onum, oden = chk_frac(other_fraction) snum = self.num * oden onum = self.den * onum if snum > onum: return True return False def __ge__(self, other_fraction): onum, oden = chk_frac(other_fraction) snum = self.num * oden onum = self.den * onum if snum >= onum: return True return False def __lt__(self, other_fraction): onum, oden = chk_frac(other_fraction) snum = self.num * oden onum = self.den * onum if snum < onum: return True return False def __le__(self, other_fraction): onum, oden = chk_frac(other_fraction) snum = self.num * oden onum = self.den * onum if snum <= onum: return True return False def __ne__(self, other_fraction): onum, oden = chk_frac(other_fraction) snum = self.num * oden onum = self.den * onum if snum != onum: return True return False def __radd__(self, other_fraction): """ __radd__ is for when the reverse adding is needed like 1 + x instead of x + 1 """ return self.__add__(other_fraction) def __iadd__(self, ofrac): """ __iadd is for increment addition x += 5 """ onum, oden = chk_frac(ofrac) snum = self.num * oden + onum * self.den sden = self.den * oden return Fraction(snum, sden) def __repr__(self): """ __repr__ is similar to __str__ because it returns a string that displays the state of the object but __repr__ can be used to recreate the object while __str__ prints the state in a human readable format. """ return f"Fraction({self.num}, {self.den})" def show(self): print("{:d}/{:d}".format(self.num, self.den)) def get_num(self): return self.num def get_den(self): return self.den x = Fraction(1, 2) x.show() y = Fraction(2, 3) print(y) assert y == Fraction(2,3) print(x + y) assert x + y == Fraction(7,6) print(x == y) """# COMPLETE THE FRACTION CLASS You can also find these questions in the book.
1. Implement the simple methods get\_num and get\_den that will return the numerator and denominator of a fraction. 2. In many ways it would be better if all fractions were maintained in lowest terms right from the start. Modify the constructor for the Fraction class so that GCD is used to reduce fractions immediately. Notice that this means the \_\_add\_\_ function no longer needs to reduce. Make the necessary modifications. 3. Implement the remaining simple arithmetic operators (\_\_sub\_\_, \_\_mul\_\_, and \_\_truediv\_\_). 4. Implement the remaining relational operators (\_\_gt\_\_, \_\_ge\_\_, \_\_lt\_\_, \_\_le\_\_, and \_\_ne\_\_). 5. Modify the constructor for the fraction class so that it checks to make sure that the numerator and denominator are both integers. If either is not an integer, the constructor should raise an exception. 6. In the definition of fractions we assumed that negative fractions have a negative numerator and a positive denominator. Using a negative denominator would cause some of the relational operators to give incorrect results. In general, this is an unnecessary constraint. Modify the constructor to allow the user to pass a negative denominator so that all of the operators continue to work properly. 7. Research the \_\_radd\_\_ method. How does it differ from \_\_add\_\_? When is it used? Implement \_\_radd\_\_. 8. Repeat the last question but this time consider the \_\_iadd\_\_ method. 9. Research the \_\_repr\_\_ method. How does it differ from \_\_str\_\_? When is it used? Implement \_\_repr\_\_. """ #Test 1 x.get_num() assert x.get_num() == 1 y.get_den() assert y.get_den() == 3 # Test 2 z = Fraction(3,6) print(z) #should be 1/2 assert z == Fraction(1,2) # Test 3 # __sub__ z = x-y print(z) assert z == Fraction(-1,6) # __mul__ z = x*y print(z) assert z == Fraction(1,3) # __truediv__ # from __future__ import division #this might need to be imported z = x/y print(z) assert z == Fraction(3,4) # Test 4 # __gt__ assert (x>y) == False # __ge__ assert (x>=y) == False # __lt__ assert (x