How do I create the divide method in Python?
This is my code:
# Rational numbers
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)
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 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
def __mul__(self, param_Rational):
''' Multiply two Rationals '''
if type(param_Rational) == int:
param_Rational = Rational(param_Rational)
if type(param_Rational) == Rational:
#multiply
denom_zero_check = self.denom
second_denom_zero_check = param_Rational.denom
if denom_zero_check & second_denom_zero_check > 0:
numer_mul = self.numer*param_Rational.numer
denom_mul = self.denom*param_Rational.denom
return Rational(int(numer_mul),int(denom_mul))
else:
print("Denominator can't be zero.")
else:
print("Wrong type in subtraction method")
raise(TypeError)
""" """
def __truediv__(self): # <-------- Here is where TypeError occurs #
''' Divide two Rationals '''
if type(param_Rational) == int:
param_Rational = Rational(param_Rational)
if type(param_Rational) == Rational:
#multiply
denom_zero_check = self.denom
second_denom_zero_check = param_Rational.denom
if denom_zero_check & second_denom_zero_check > 0:
numer_mul = self.numer*param_Rational.denom
denom_mul = self.denom*param_Rational.numer
return Rational(int(numer_mul),int(denom_mul))
else:
print("Denominator can't be zero.")
And I'm getting the error (location marked above):
TypeError: __truediv__() takes 1 positional argument but 2 were given
How do I fix this? I got the multiplication down but not the divide, should I use div or truediv? And do I need to use / in the actual div method?
How can __truediv__ only take one argument? You need two, self and the divisor. The same way your __mul__ __add__, and __sub__ needed a second argument.
def __truediv__(self, param_Rational):
# rest of your code
Instead of first printing an error message and then raising the error, you can use:
raise TypeError("Wrong type in addition method.")
Also, it might be usefull to check wether the demnominator is 0 or not in init(), and raise ZeroDivisionError if it is.
PS: 2/3 / 6/9 should equal 1/1 as 2/3=6/9=0.666...
Related
In part of my code I can subtract fractions, however if I enter (- p) where p is a fraction I get a TypeError: unsupported operand type(s) for +: "Fraction" and "Fraction"
def gcd(denominator, numerator):
if numerator == 0:
return denominator
else:
return gcd(numerator, (denominator % numerator))
class Fraction:
def __init__(self,numerator = 0, denominator = 1):
self.numerator = int(numerator / gcd(abs(denominator),abs(numerator) ))
self.denominator = int(denominator / gcd(abs(denominator),abs(numerator) ))
if self.denominator < 0:
self.denominator = abs(self.denominator)
self.numerator = -1*self.numerator
elif self.denominator == 0:
raise ZeroDivisionError
def __str__(self):
if self.denominator == 1:
return str(self.numerator)
else:
return str(self.numerator) + "/" + str(self.denominator)
def __rsub__(self,other):
return self.__sub__(other)
def __sub__(self,other):
if type(other) == int:
other = Fraction(other,1)
return self.sub(other)
else:
return self.sub(other)
def sub(self,other):
result = Fraction()
result.numerator = other.denominator * self.numerator - self.denominator * other.numerator
result.denominator = other.denominator * self.denominator
multiple = gcd(result.denominator,result.numerator)
result.numerator = int(result.numerator / multiple)
result.denominator = int(result.denominator / multiple)
return result
p = Fraction(2,3)
r = (- p)
However, when my input is (1 - p) I get the correct output. Suppose p = Fraction(2, 3) then I would like (- p) to return (-2 / 3) or (2/ -3). The problem seems to me to be in the fact that no input is given for the first argument when subtracting. While searching I did come across things like __neg__, but I'm still new to python and using classes so I don't know exactly how to implement this. Does anyone know how I can fix this?
Thanks in advance!
You are right; you need to implement __neg__ because that minus is not the (binary) subtraction operator, but the unary minus.
Here is how you can do it:
def __neg__(self):
return Fraction(-self.numerator, self.denominator)
Other issues
__rsub__
You need to change the implementation of __rsub__, because that method will be called when other does not support __sub__. For instance, it will kick in when you evaluate this:
p = 1 - Fraction(2, 3)
That evaluation will not work as it currently stands. You need to have this:
def __rsub__(self, other):
return Fraction(other) - self
or, explicitly calling __sub__:
def __rsub__(self, other):
return Fraction(other).__sub__(self)
Normalising
The constructor correctly normalises the fraction, making sure the denominator is positive, but you don't do the same in the sub method. There the result may not be normalised: the denominator could remain negative.
Moreover, it is a pity that you duplicate the gcd-related code that is already in the constructor. It is better to rely on the constructor for that logic.
Immutability
It is better to treat instances as immutable. So you should not have any assignments to instance.numerator and instance.denominator outside of the constructor. Make sure to first determine the numerator and denominator (without normalisation), and then call the constructor passing these as arguments.
Comparisons
You may want to compare Fractions for equality or relative order. For that you can implement __eq__, __lt__, ...etc.
Proposed code
Here is how I would do it:
def gcd(denominator, numerator):
if numerator == 0:
return denominator
else:
return gcd(numerator, denominator % numerator)
class Fraction:
def __new__(cls, numerator=0, denominator=1):
if isinstance(numerator, Fraction):
return numerator # Use this instance and ignore 2nd argument
return super(Fraction, cls).__new__(cls)
def __init__(self, numerator=0, denominator=1):
if isinstance(numerator, Fraction):
return # self is already initialised by __new__
if denominator == 0:
raise ZeroDivisionError
div = gcd(abs(denominator), abs(numerator))
if denominator < 0:
div = -div
self.numerator = numerator // div
self.denominator = denominator // div
def __str__(self):
if self.denominator == 1:
return str(self.numerator)
else:
return f"{self.numerator}/{self.denominator}"
def __rsub__(self, other):
return Fraction(other) - self
def __sub__(self, other):
other = Fraction(other)
return Fraction(other.denominator * self.numerator
- self.denominator * other.numerator,
other.denominator * self.denominator)
def __neg__(self):
return Fraction(-self.numerator, self.denominator)
def __eq__(self, other):
other = Fraction(other)
return (self.numerator == other.numerator and
self.denominator == other.denominator)
def __lt__(self, other):
other = Fraction(other)
return (other.denominator * self.numerator <
self.denominator * other.numerator)
def __gt__(self, other):
return Fraction(other) < self
def __le__(self, other):
return self < other or self == other
def __ge__(self, other):
return self > other or self == other
Your __rsub__ code is flipped, you want other.__sub__(self).
def __rsub__(self,other):
return other.__sub__(self)
I am doing a task where I have a class Fractions which contains functions as to how I can add, subtract, multiply and divide the fractions. I am having trouble creating the add function which will be adding 2 fractions and this function must use the staticmethod. This is the code that I have written so far:
class Fraction:
def __init__(self,num1=0,num2=0):
self.num1=num1
self.num2=num2
def __str__(self):
while self.num1>self.num2:
a = self.num1//self.num2
b = self.num1 % self.num2
if self.num2==1:
return "%s"%(self.num1)
elif self.num1 % self.num2==0:
return "%s"%(self.num1/self.num2)
else:
return "%s+%s|%s"%(a,b,self.num2)
if self.num1==0:
return "0"
elif self.num1 or self.num2 < 0 and self.num1==self.num2:
return "-1"
elif self.num2==1:
return "%s"%(self.num1)
elif self.num1==self.num2:
return "1"
else:
return "%s|%s"%(self.num1,self.num2)
#staticmethod
def add(a,b):
a=Fraction(n,d)
b=Fraction(num,den)
if a.d == b.den and a.n<a.d or b.num<b.den:
return "%s|%s"%(a.n+b.num,a.d)
elif a.d != b.den:
return "%s|%s"%((a.n*b.den)+(a.d*b.num),(a.d*b.den))
I am facing trouble in trouble in the add function and I do not know how to make the function work.
For example:
Fraction.add(Fraction(1,4),Fraction(2,4))
>>> 3|4
Fraction.add(Fraction(1,5),Fraction(6,7))
>>> 1 + 2|35
This is what the output should look like. Could anyone guide me through the add function and how I can improve it using the staticmethod
If the arguments a and b are already Fraction objects, then you would use the attributes from them directly in your method:
#staticmethod
def add(a,b):
if a.num2 == b.num2 and (a.num1 < a.num2 or b.num1 < b.num2):
return "%s|%s"%(a.num1 + b.num1, a.num2)
elif a.num2 != b.num2:
return "%s|%s"%((a.num1 * b.num2) + (a.num2 * b.num1), (a.num2 * b.num2))
There were also a missing parenthesis in the first if clause.
This question already has answers here:
How do I call a method from another method?
(3 answers)
Closed 2 years ago.
I am new python programmer and trying to write Python class with 2 functions and calling one from another.
below is my code, can someone please help me in fixing the code.
class Solution:
def repeat_check(string):
for i in range(1, len(string)//2+1):
if not len(string)%len(string[0:i]) and string[0:i]*(len(string)//len(string[0:i])) == string:
return string[0:i]
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
fraction = str(numerator/denominator)
decimal_pos = fraction.index('.')
repeat_string = str(fraction[decimal_pos+1:])
if numerator%denominator==0:
return fraction
elif numerator%denominator!=0 and repeat_check(repeat_string) is None:
return repeat_string
elif numerator%denominator!=0 and repeat_check(repeat_string).isdigit():
return fraction+'.('+repeat_string+')'
I got error message name "repeat_check is not defined"
input
numerator = 2 denominator = 3
output
0.(6)
You are missing "self" in the repeat_check method:
class Solution:
def repeat_check(self, string):
for i in range(1, len(string) // 2 + 1):
if not len(string) % len(string[0:i]) and string[0:i] * (len(string) // len(string[0:i])) == string:
return string[0:i]
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
fraction = str(numerator / denominator)
decimal_pos = fraction.index('.')
repeat_string = str(fraction[decimal_pos + 1:])
if numerator % denominator == 0:
return fraction
elif numerator % denominator != 0 and self.repeat_check(repeat_string) is None:
return repeat_string
elif numerator % denominator != 0 and self.repeat_check(repeat_string).isdigit():
return fraction + '.(' + repeat_string + ')'
First of all I reccomend you to make indents. Therefore the Function will be a field of the class.
Scond: Every Function of the class gets the "self" argument. and then you can refer it with self.repeat_check().
Best regards
I'm working on an assignment where I make a class called Triangle that takes in three sides and returns information about the triangle. Specifically, I am trying to calculate the three angles within the triangle, but for some reason I am getting 90 degrees for all angles, which is impossible. I have gone over my code tons of times but can't find the mistake and would greatly appreciate some help. Thank you.
from math import acos, degrees, sqrt
import turtle
class Triangle:
def __init__(self, side_a=None, side_b=None, side_c=None):
self.side_a = side_a
self.side_b = side_b
self.side_c = side_c
def is_triangle(self):
return ((self.side_a + self.side_b) > self.side_c) \
and ((self.side_a + self.side_c) > self.side_b) \
and ((self.side_b +self.side_c) > self.side_a)
def perimeter(self):
if self.is_triangle():
return self.side_a + self.side_b + self.side_c
else:
return None
def area(self):
if self.is_triangle():
s = self.perimeter()/2
print s
return sqrt((s*(s-self.side_a)*(s-self.side_b)*(s-self.side_c)))
else:
return None
def a_angle(self):
if self.is_triangle():
return degrees(acos((self.side_b**2 + self.side_c**2 - self.side_a**2)/(2*self.side_b*self.side_c)))
else:
return None
def b_angle(self):
if self.is_triangle():
return degrees(acos((self.side_c**2 + self.side_a**2 - self.side_b**2)/(2*self.side_c*self.side_a)))
else:
return None
def c_angle(self):
if self.is_triangle():
return degrees(acos((self.side_a**2 + self.side_b**2 - self.side_c**2)/(2*self.side_a*self.side_b)))
else:
return None
def angle(self):
return self.a_angle(), self.b_angle(), self.c_angle()
def __str__(self):
pass
tri = Triangle(11, 7, 9)
print tri.is_triangle()
print tri.perimeter()
print tri.area()
print tri.a_angle()
print tri.b_angle()
print tri.c_angle()
print tri.angle()
In Python 2, division of integers by default truncates the result to an integer, so something like 5/2 will equal 2. In your case, dividing the sides results in zero.
The simplest way to fix it is to do from __future__ import division at the very beginning of your file. This makes division always return a float.
def gcd(bigger, smaller):
"""Calculate the greatest common divisor of two positive integers."""
print('in gcd')
if not bigger > smaller: # swap if necessary so bigger > smaller
bigger, smaller = smaller, bigger
while smaller != 0: # 1. if smaller == 0, halt
remainder = bigger % smaller # 2. find remainder
# print('calculation, big:{}, small:{}, rem:{}'.\
# format(bigger, smaller, remainder)) # debugging
bigger, smaller = smaller, remainder # 3. reapply
return bigger
def lcm (a,b):
"""Calculate the lowest common multiple of two positive integers."""
print('in lcm')
return (a*b)//gcd(a,b) # Equation 12.1, // ensures int is returned
class Rational(object):
""" Rational with numerator and denominator. Denominator
parameter 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 interpreter. Call __str__ for now """
print('in repr')
return self.__str__()
def __div__(self, param_Rational):
print("in div")
new_param = Rational(param_Rational.denom, param_Rational.numer)
return self.__mul__(new_param)
def __mul__(self, param_Rational):
print("in mult")
if type(param_Rational) == int:
param_Rational = Rational(param_Rational)
if type(param_Rational) == Rational:
new_numerator = self.numer * param_Rational.numer
new_denominator = self.denom * param_Rational.denom
return Rational(new_numerator, new_denominator)
else:
raise("type error")
def __rmul__(self, param):
print("in rmul")
return self.__mul__(param)
When I try to implement >>> Rational(4, 1) / Rational(2, 1)
but it shows the type error "unsupported operand type(s) for /: 'Rational' and 'Rational'", which shows that the division function is not implemented.
I think the division function should be implemented like the code "div" above, so I don't really now what's wrong with this code. Could anyone give some advices please?
The __div__() method is not used in Python 3.x. Implement __truediv__() instead.