Basil Basil - 1 month ago 16
Python Question

Comparing custom Fractions

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).

Answer

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