Reputation:
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).
Upvotes: 1
Views: 296
Reputation: 298392
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
Upvotes: 2