Comparing custom Fractions - python

I'm working through a book now and I have a question regarding one of exercises (#6).
So we have a hand-made Fraction class and, besides all other kinds of things, we want to compare two fractions.
class Fraction:
def __init__(self, num, den):
if not (isinstance(num, int) and isinstance(den, int)):
raise ValueError('Got non-int argument')
if den == 0:
raise ValueError('Got 0 denominator')
self.num = num
self.den = den
# some class methods
def __lt__(self, other):
selfnum = self.num * other.den
othernum = other.num * self.den
return selfnum < othernum
# some class methods
# trying it out
x = Fraction(1, -2)
y = Fraction(1, 3)
However, when we evaluate x < y, the result is False. I thought of making new attribute to store sign, but that messes everything up quite a bit.
Due to lack of better alternative, I added if in the method, and here's what I got
def __lt__(self, other):
selfnum = self.num * other.den
othernum = other.num * self.den
if self.den * other.den > 0:
return selfnum < othernum
else:
return selfnum > othernum
Although it seems to be working, I wonder, if there is more elegant solution.
Update
Storing sign in numerator does what I wanted (I can just change 2 lines instead of adding a conditional in each method).

If you assume that both denominators are positive, you can safely do the comparison (since a/b < c/d would imply ad < bc). I would just store the sign in the numerator:
self.num = abs(num) * (1 if num / den > 0 else -1)
self.den = abs(den)
Or:
self.num = num
self.den = den
if self.den < 0:
self.num = -self.num
self.den = -self.den
And your __lt__ method can be:
def __lt__(self, other):
return self.num * other.den < other.num * self.den

Related

Python: Operation between integer and custom class

I created a class called Rational - which represents a rational number - with a method that allows it to be added to another Rational object, but am having a hard time figuring out a way to allow it to be added to an integer object through a method inside the Rational class.
# This already works
a = Rational(1,2);
b = Rational(1,1)
# a+b -> 3/2
# This is what I wish also worked
a+1 = 3/2
The code I have:
class Rational:
def __init__(self,num:int,den:int=1):
self.num = num
self.den = den
try:
value = self.num/self.den
except:
print("O denominador não pode ser 0.")
def __str__(self):
if self.den == 1:
return f"{self.num}"
elif self.den > 0:
return f"{self.num}/{self.den}"
elif self.den < 0:
return f"{-self.num}/{-self.den}"
def __add__(self, other):
if self.den != other.den:
num_new = (self.num*other.den) + (other.num*self.den)
den_new = self.den*other.den
else:
num_new = self.num + other.num
den_new = self.den
return Rational(num_new,den_new)
Is there a simple way to make this happen?

GCD implementation of fraction addition not working properly

I am following the Runestone Academy Python3 course and tried to implement 'addition' feature for fractions using Class but I am getting error.
When I am not using GCD implementation, the code is running fine
Here is my code:
class Fraction:
def __init__(self, top, bottom):
self.num = top
self.den = bottom
def show(self):
print(f'{self.num}/{self.den}')
def __str__(self):
return f'{self.num}/{self.den}'
# adding without GCD implementation
# def __add__(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# adding with GCD implementation
def gcd(self, m, n):
while m % n != 0:
m, n = n, m % n
return n
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
# my attempt of adding two fractions by creating a method 'add'
# def add(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# my_fraction = Fraction(3,5)
# print(my_fraction)
# print(f'I ate {my_fraction} of my pizza')
# my_fraction.__str__()
# str(my_fraction)
f1 = Fraction(1, 4)
f2 = Fraction(1, 2)
f3 = f1 + f2
# f3 = f1.add(f2)
print(f3)
This is the error I am getting:
Traceback (most recent call last):
File "D:/Python/Mosh_Lec/app.py", line 74, in <module>
f3 = f1 + f2
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
I also tried with this variation but same error:
def gcd(self, m, n):
self.num = m
self.den = n
while self.num % self.den != 0:
self.num, self.den = self.den, self.num % self.den
return self.den
The gcd method should not logically be part of the Fraction class. Indeed, you can call the gcd method with any two numbers, they do not need to be the numerator and denominator of a fraction. Therefore I would move the gcd function outside of the class.
def gcd(m, n):
...
class Fraction:
...
Look at there:
NameError: name 'gcd' is not defined
It means that it cannot find the function(or method) named gcd. Of course! It need to be called with a Fraction object, so try to change your source code at line 32:
- common = gcd(new_num, new_den)
+ common = self.gcd(new_num, new_den)
self is a Fraction object.
By the way, the method gcd that do not use the parament self should be defined as a static function:
class Fraction:
...
#staticmethod
def _gcd(m: int, n: int):
...
...
And call the method by Fraction._gcd (the underline means that it is private function(or method)).
See it's a simple issue if u see the error:
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
you will see that you have defined gcd but why it is saying GCD, not defined here's the reason:
common = self.gcd(new_num, new_den)
It is as simple as that just put the above code like this:
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = self.gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
and your problem is solved! Kudos!
It as simple as that.......

Division of complex numbers in Python 3 class

I am having trouble creating a __div__ method in a Python class for complex numbers which should divide two complex numbers.
Here is my code:
class Complex(object):
def __init__(self, real = 0, imag = 0):
self.real = real
self.imag = imag
def __str__(self):
if self.imag > 0:
return str(self.real) + "+" + str(self.imag) + "i"
elif self.imag < 0:
return str(self.real) + str(self.imag) + "i"
def __div__(self, other):
x = self.real * other.real + self.imag * other.imag
y = self.imag * other.real - self.real * other.imag
z = other.real**2 + other.imag**2
real = x / z
imag = y / z
return Complex(real, imag)
no = Complex(2,-8)
no2 = Complex(3,7)
print(no/no2)
Unfortunately, my approach doesn't work. Any suggestions?
__div__ doesn't exist anymore in Python 3. It's been replaced by __truediv__ for / and __floordiv__ for //
Have a look at
https://docs.python.org/3/reference/datamodel.html
It's __truediv__, not __div__. __div__ was the name for the old Python 2 "floordiv for integer, truediv for non-integer" division.
While you're fixing things, you should probably add an else case in __str__.
you need to create a method __div__(self, other) where you divide the no and also a new method __opposite__(self) to change the sign when multipy,
also calling method how to devide ie no/no1 is not a god method
using #johnO solution, overwiting __truediv__
so OP can use no/no2 to division two complex numbers.
see code below
class Complex(object):
def init(self, real = 0, imag = 0):
self.real = real
self.imag = imag
def __str__(self):
if self.imag > 0:
return str(self.real) + "+" + str(self.imag) + "i"
elif self.imag < 0:
return str(self.real) + str(self.imag) + "i"
def __opposite__(self):
self.real =self.real
self.imag = self. imag if self.imag<0 else self.imag * -1
def __truediv__(self, other):
other.__opposite__()
x = self.real * other.real - self.imag * other.imag
y = self.imag * other.real + self.real * other.imag
z = other.real**2 + other.imag**2
self.new_real = x / z
self.new_imag = y / z
if self.new_imag>0:
result = "{} + {}i".format(self.new_real, self.new_imag)
else:
result = "{} {}i".format(self.new_real, self.new_imag)
return result
no = Complex(4,5)
no2 = Complex(2,6)
print(no/no2)
output
0.24 + 0.68i

making Fraction class by my own

I'm trying to make my 'own Fraction class'.
Almost all code work fine, but at /, >, <, these are not working.
I have no idea what's wrong with my code.
def gcd(m, n):
while m%n != 0:
m, n = n, m%n
return n
class Fraction:
'''Fractional class'''
def __init__(self, num, denom):
self.num = num
self.denom = denom
def __str__(self):
return str(self.num)+'/'+str(self.denom)
def __add__(self, other):
new_num = self.num * other.denom + other.num * self.denom
new_denom = self.denom * other.denom
common = gcd(new_num, new_denom)
return Fraction(new_num//common, new_denom//common)
def __sub__(self, other):
new_num = self.num * other.denom - other.num * self.denom
new_denom = self.denom * other.denom
common = gcd(new_num, new_denom)
return Fraction(new_num//common, new_denom//common)
def __mul__(self, other):
new_num = self.num * other.num
new_denom = self.denom * other.denom
common = gcd(new_num, new_denom)
return Fraction(new_num//common, new_denom//common)
def __div__(self, other):
new_num = self.num * other.denom
new_denom = self.denom * other.num
common = gcd(new_num, new_denom)
return Fraction(new_num//common, new_denom//common)
def __equal__(self, other):
return (self.num * other.denom) == (other.num * self.denom)
def __big__(self, other):
return str(self.num * other.denom) > str(other.num * self.denom)
def __small__(self, other):
return self.num * other.denom < other.num * self.denom
if __name__ == "__main__":
f1 = Fraction(1,4)
f2 = Fraction(1,2)
print(f1+f2)
print(f1 - f2)
print(f1 * f2)
print(f1 / f2) #not working
print(f1 == f2)
print(f1 > f2) #not working
print(f1 < f2) #not working
I get the following output:
3/4
-1/4
1/8
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-50-50cad0951bd1> in <module>()
57 print(f1 - f2)
58 print(f1 * f2)
---> 59 print(f1 / f2) #not working
60
61 print(f1 == f2)
TypeError: unsupported operand type(s) for /: 'Fraction' and 'Fraction'
Am I defining __div__ correctly?
Python 3.x uses __truediv__ and __floordiv__. __div__ is used in python 2.x.
To make comparison work you need to define __lt__, __gt__, __ge__ and __le__.

Module Won't recognize my function

I have a code for a Fraction class
class Fraction:
def __init__(self,top,bottom):
self.num = top
self.den = bottom
def __str__(self):
return str(self.num)+"/"+str(self.den)
def show(self):
print(self.num,"/",self.den)
def gcd(m,n):
while m%n != 0:
oldm = m
oldn = n
m = oldn
n = oldm%oldn
return n
def __add__(self,otherfraction):
newnum = self.num*otherfraction.den + \
self.den*otherfraction.num
newden = self.den * otherfraction.den
common = gcd(newnum,newden)
return Fraction(newnum//common,newden//common)
def __eq__(self, other):
firstnum = self.num * other.den
secondnum = other.num * self.den
return firstnum == secondnum
When I run it and try to add two fractions it pops up saying
File "/Users/----/Downloads/Listings/listing_1_9.py", line 25,
in __add__
common = gcd(newnum,newden)
NameError: global name 'gcd' is not defined
In your code, gcd is a method of Fraction, so you should use self.gcd when referring to it from inside another method.
Use self.gcd instead.
Explanation
NameError: global name 'gcd' is not defined
Thats because gcd is not a global. Its a method of Fraction.

Categories

Resources