If your rationals have reduced all common factors out of numerator and denominator, then you can do this:
return (numerator == r.numerator) && (denominator == r.denominator);
If your rationals have not done that factorization, then I suggest you implement a GCD function that will allow you to do that. Then compare the reduced numerator
and denominator
against the reduced r.numerator and r.denominator
.
Example, assuming int
is the underlying type for your rational numerator and denominator:
int gcd_lhs = gcd( numerator, denominator );
int gcd_rhs = gcd( r.numerator, r.denominator );
int lhs_red_num = numerator / gcd_lhs;
int lhs_red_den = denominator / gcd_lhs;
int rhs_red_num = r.numerator / gcd_rhs;
int rhs_red_den = r.denominator / gcd_rhs;
return (lhs_red_num == rhs_red_num) && (lhs_red_den == rhs_red_den);
This approach has the advantage of being exact in all cases, and it will never exceed the precision of the underlying type that you're using for numerator and denominator.
Approaches relying on multiplication, or on dividing something out of the values other than the GCD risk overflowing the precision available in the underlying types. (Division can "overflow" the available precision by producing a repeating binary fraction that must be rounded to fit in the available bits, assuming you cast to double
first. Dividing by GCD is always exact, and remain as integer division.)
You can mitigate that by using a BigInteger type and applying the cross-multiplication approach. That has its own costs. If you're already using BigInteger to store numerator and denominator, that may be the easiest approach, though.