Home > Blockchain >  Can I naively check if a/b == c/d?
Can I naively check if a/b == c/d?

Time:08-17

I was doing leetcode when I had to do some arithmetic with rational numbers (both numerator and denominator integers).

I needed to count slopes in a list. In python

collections.Counter( [ x/y if y != 0 else "inf" for (x,y) in points ] )

did the job, and I passed all the tests with it. ((edit: they've pointed out in the comments that in that exercise numbers were much smaller, not general 32 bit integers))

I wonder if this is correct, that is, python correctly recognizes if a/b == c/d as rationals, for a,b,c,d 32 bit integers. I am also interested the case for c , and any additional facts that may be useful (footguns, best practices, theory behind it if not too long etc).

Also this question seems frequent and useful, but I don't really find anything about it (give me the duplicates!), maybe I am missing some important keywords?

CodePudding user response:

It's not safe, and I've seen at least one LeetCode problem where you'd fail with that (maybe Max Points on a Line). Example:

a = 94911150
b = 94911151
c = 94911151
d = 94911152
print(a/b == c/d)
print(a/b)
print(c/d)

Both a/b and c/d are the same float value even though the slopes actually differ (Try it online!):

True
0.9999999894638303
0.9999999894638303

You could use fractions.Fraction(x, y) or the tuple (x//g, y//g) after g = math.gcd(d, y) ( if I remember correctly, this is more lightweight/efficient than the Fraction class).

CodePudding user response:

Assuming you don't want to allow for the effects of integer division, check the equivalent ad == bc instead.

This is more numerically stable. In C you can write

1LL * a * d == 1LL * b * c

to prevent overflow.

  • Related