6 Replies - 380 Views - Last Post: 26 October 2017 - 05:56 PM Rate Topic: -----

#1 forumer444  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 30
  • Joined: 19-September 17

I have a homework question.

Posted 23 October 2017 - 03:36 PM

I'm writing a program to perform arithmetic operations on Rational Numbers. I have each piece working correctly, but I'm confused on how to get the
reduce_rational(self):
method to reduce the calculated sum, difference, product and quotient.

Here's what I have and it works:

def gcd(bigger, smaller):
    ''' compute the greatest common divisor of two positive integers '''
    # print(' in gcd ')
    if not bigger > smaller :
        bigger, smaller = smaller, bigger
    while smaller != 0:
        remainder = bigger % smaller
        # print('gcd calc, big:{}, small:{}, rem:{}' \
        #        .format(bigger, smaller, remainder))
        bigger, smaller = smaller, remainder
    return bigger

def lcm(a, B)/>:
    ''' calculate the least common multiple of two positive integers '''
    # print(' in lcm ')
    return (a * B)/> // gcd(a, B)/>

def division(a, B)/>:
    ''' calculate the least common multiple of two positive integers '''
    # print(' in lcm ')
    return (a * B)/> // gcd(a, B)/>
def multiplication(a, B)/>:
    
    ''' calculate the least common multiple of two positive integers '''
    # print(' in multiplication ')
    return (a // B)/>;
# ----------------------------------class-------------------------------------
class Rational(object):
    ''' rational with numerator and denominator. Denominator defaults to 1 '''
    def __init__(self, numer, denom = 1):
        # print(' in constructor ')
        self.numer = numer
        self.denom = denom

    def __str__(self):
        ''' string representation for printing '''
        # print(' in str ')
        return str(self.numer)  + '/'  +  str(self.denom)

    def __repr__(self):
        ''' used in the interpreter. Call __str__ for now '''
        print(' in repr ')
        return self.__str__()

    def __add__(self, param_Rational):
        ''' add two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # find the lcm
            the_lcm = lcm(self.denom, param_Rational.denom)
            # multiply each numerator by the lcm, then add
            numerator_sum = the_lcm * self.numer / self.denom + \
                        the_lcm * param_Rational.numer / param_Rational.denom
            return Rational(int(numerator_sum), the_lcm)
        else:
            print("Wrong type in addition method.")
            raise(TypeError)

    def __sub__(self, param_Rational):
        ''' subtract two rationals '''
        # print(' in add ')
        # find the lcm
        the_lcm = lcm(self.denom, param_Rational.denom)
        # multiply each numerator by the lcm, then add
        numerator_sum = the_lcm * self.numer / self.denom - \
                    the_lcm * param_Rational.numer / param_Rational.denom
        return Rational(int(numerator_sum), the_lcm)

    def __mul__(self, param_Rational):
        ''' multiply two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # multiply  numerator
            numerator_mul = self.numer * param_Rational.numer
            # multiply denominator
            denominator_mul = self.denom * param_Rational.denom
            return Rational(int(numerator_mul), int(denominator_mul))
        else:
            print("Wrong type in multiplication method.")
            raise(TypeError)

    def __truediv__(self, param_Rational):
        ''' divide two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # multiply  numerator
            numerator_mul = self.numer * param_Rational.denom
            # multiply denominator
            denominator_mul = self.denom * param_Rational.numer
            return Rational(int(numerator_mul), int(denominator_mul))
        else:
            print("Wrong type in division method.")
            raise(TypeError)

    def reduce_rational(self):
        ''' return the reduced fraction value as a rational '''
        # find the gcd and divide numerator and denominator by it
        the_gcd = gcd(self.numer, self.denom)
        return Rational(self.numer // the_gcd, self.denom // the_gcd)

    def __eq__(self, param_Rational):
        ''' compare two rationals for equalit and return a boolean '''
        reduced_self  = self.reduce_rational()
        reduced_param = param_Rational.reduce_rational()
        return reduced_self.numer == reduced_param.numer and \
               reduced_self.denom == reduced_param.denom
# -----------------------------------main-------------------------------------
def main():
    r1 = Rational(1, 2)
    r2 = Rational(1, 4)
    print("First Rational Number:",     r1.__str__())
    print("Second Rational Number:",    r2.__str__())
    print("Sum:",                       r1.__add__(r2))
    print("Difference:",                r1.__sub__(r2))
    print("Product:",                   r1.__mul__(r2))
    print("Quotient:",                  r1.__truediv__(r2))
if __name__ == "__main__":
    main()


This is the output!

First Rational Number: 1/2
Second Rational Number: 1/4
Sum: 3/4
Difference: 1/4
Product: 1/8
Quotient: 4/2


But how do I get it reduced?

I tried:
def main():
    r1 = Rational(1, 2)
    r2 = Rational(1, 4)
    print("First Rational Number:",     Rational.reduce_rational(r1.__str__()))
    print("Second Rational Number:",    Rational.reduce_rational(r2.__str__()))
    print("Sum:",                       Rational.reduce_rational(r1.__add__(r2)))
    print("Difference:",                Rational.reduce_rational(r1.__sub__(r2)))
    print("Product:",                   Rational.reduce_rational(r1.__mul__(r2)))
    print("Quotient:",                  Rational.reduce_rational(r1.__truediv__(r2)))


... but got an AttributeError.

Please help. I'm kind of new to classes in Python.

Is This A Good Question/Topic? 0
  • +

Replies To: I have a homework question.

#2 Martyr2  Icon User is offline

  • Programming Theoretician
  • member icon

Reputation: 5074
  • View blog
  • Posts: 13,697
  • Joined: 18-April 07

Re: I have a homework question.

Posted 23 October 2017 - 04:16 PM

Your methods return a Rational Object from their calculations, so you can't just past those to reduce_rational because that is an instance method that doesn't take objects as parameters. You need to call the method on the instance returned from your method calls. Try something like this...

def main():
    r1 = Rational(1, 2)
    r2 = Rational(1, 4)


    print("Quotient: ", r1.__truediv__(r2).reduce_rational())



Notice here that we are taking the object returned from your method (a Rational object itself) and then calling its reduce_rational() method. This should give you 2/1 which is 2 and the answer to your division of rationals. :)

This post has been edited by Martyr2: 23 October 2017 - 04:18 PM

Was This Post Helpful? 0
  • +
  • -

#3 forumer444  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 30
  • Joined: 19-September 17

Re: I have a homework question.

Posted 23 October 2017 - 04:54 PM

Ah, I see! Thanks for your help! I have one more question though, what is the difference between __div__ and __truediv__? In my assignment description, it says "Instead of __div__, you must use __truediv__ to implement the division operator." All I did is literally change the name from "div" to "truediv" and have no idea what difference it makes...
Was This Post Helpful? 0
  • +
  • -

#4 ndc85430  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 594
  • Posts: 2,490
  • Joined: 13-June 14

Re: I have a homework question.

Posted 24 October 2017 - 01:10 AM

__truediv__ always does floating point division, rather than integer division as __div__ does, e.g.

>>> import operator
>>> operator.__div__(2, 3)
0
>>> operator.__truediv__(2, 3)
0.6666666666666666
>>> 


Was This Post Helpful? 0
  • +
  • -

#5 forumer444  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 30
  • Joined: 19-September 17

Re: I have a homework question.

Posted 26 October 2017 - 04:27 PM

View Postndc85430, on 24 October 2017 - 01:10 AM, said:

__truediv__ always does floating point division, rather than integer division as __div__ does, e.g.

>>> import operator
>>> operator.__div__(2, 3)
0
>>> operator.__truediv__(2, 3)
0.6666666666666666
>>> 


Oh, okay. Thanks!

Do you mind helping me with one more problem?
Was This Post Helpful? 0
  • +
  • -

#6 forumer444  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 30
  • Joined: 19-September 17

Re: I have a homework question.

Posted 26 October 2017 - 04:35 PM

So I'm trying to implement __rsub__() and __rtruediv__() methods in my program to be able to handle integers that aren't created instances (rational numbers) of my class.

So for example, in my main program if I put:
# __sub__() assert test
r_4_5 = Rational(4, 5)
difference = Rational(21, -5) # correct difference
assert r_4_5 - 5 == difference, "Error in __sub__()method."



I want it to be equal to the right answer (obviously), but I keep on getting an attribute error.

I added the __radd__() and __rmul__() methods and they work fine, but not for subtraction and division and I don't know why.

This is my updated code:

def gcd(bigger, smaller):
    ''' compute the greatest common divisor of two positive integers '''
    if not bigger > smaller :
        bigger, smaller = smaller, bigger
    while smaller != 0:
        remainder = bigger % smaller
        bigger, smaller = smaller, remainder
    return bigger

def lcm(a, B)/>:
    ''' calculate the least common multiple of two positive integers '''
    return (a * B)/> // gcd(a, B)/>
# ----------------------------------class-------------------------------------
class Rational(object):
    ''' rational with numerator and denominator (denominator defaults to 1) '''
    def __init__(self, numer, denom = 1):
        # print("in constructor")
        self.numer = numer
        self.denom = denom

    def __str__(self):
        ''' string representation for printing '''
        # print("in str")
        return str(self.numer)  + '/'  +  str(self.denom)

    def __repr__(self):
        ''' used in the interpreter. call __str__ for now '''
        # print("int repr")
        return self.__str__()

    def __radd__(self, param_Rational):
        print("in radd")
        return self.__add__(param_Rational)

    def __add__(self, param_Rational):
        ''' add two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # find the lcm
            the_lcm = lcm(self.denom, param_Rational.denom)
            # multiply each numerator by the lcm, then add
            numerator_sum = the_lcm * self.numer / self.denom + \
                        the_lcm * param_Rational.numer / param_Rational.denom
            return Rational(int(numerator_sum), the_lcm)
        else:
            print("Wrong type in addition method.")
            raise(TypeError)

    def __sub__(self, param_Rational):
        ''' subtract two rationals '''
        # find the lcm
        the_lcm = lcm(self.denom, param_Rational.denom)
        # multiply each numerator by the lcm, then add
        numerator_sum = the_lcm * self.numer / self.denom - \
                    the_lcm * param_Rational.numer / param_Rational.denom
        return Rational(int(numerator_sum), the_lcm)

    def __rmul__(self, param_Rational):
        print("in radd")
        return self.__mul__(param_Rational)

    def __mul__(self, param_Rational):
        ''' multiply two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # multiply  numerator
            numerator_mul = self.numer * param_Rational.numer
            # multiply denominator
            denominator_mul = self.denom * param_Rational.denom
            return Rational(int(numerator_mul), int(denominator_mul))
        else:
            print("Wrong type in multiplication method.")
            raise(TypeError)

    def __truediv__(self, param_Rational):
        ''' divide two rationals '''
        if type(param_Rational) == int:
            param_Rational = Rational(param_Rational)
        if type(param_Rational) == Rational:
            # multiply  numerator
            numerator_mul = self.numer * param_Rational.denom
            # multiply denominator
            denominator_mul = self.denom * param_Rational.numer
            return Rational(int(numerator_mul), int(denominator_mul))
        else:
            print("Wrong type in division method.")
            raise(TypeError)

    def reduce_rational(self):
        ''' return the reduced fraction value as a rational '''
        # find the gcd and divide numerator and denominator by it
        the_gcd = gcd(self.numer, self.denom)
        return Rational(self.numer // the_gcd, self.denom // the_gcd)

    def __eq__(self, param_Rational):
        ''' compare two rationals for equalit and return a boolean '''
        reduced_self  = self.reduce_rational()
        reduced_param = param_Rational.reduce_rational()
        return reduced_self.numer == reduced_param.numer and \
               reduced_self.denom == reduced_param.denom


Was This Post Helpful? 0
  • +
  • -

#7 forumer444  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 30
  • Joined: 19-September 17

Re: I have a homework question.

Posted 26 October 2017 - 05:56 PM

def __rsub__(self, param_Rational):
        # print("in rsub")
        param_Rational = Rational(self.param_Rational) # incorrect, but i don't know why
        return self.__sub__(param_Rational)

def __rtruediv__(self, param_Rational):
        # print("in rtruediv")
        pass



I'm trying to convert the integer parameter to a Rational, but I'm not sure how.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1