Search code examples
c++operator-overloadingrational-numbers

Comparing Rational Numbers


I have made the following rational numbers C++ class with all the general arithmetic functions (+, -, *, /, == and !=).

template <class T>
struct rationalNumber
{
    static_assert(!std::numeric_limits<T>::is_signed, "ERROR: Type T must be unsigned");
    static_assert(std::is_integral<T>::value, "ERROR: Type T must be integral");

    T numerator;
    T denominator;
    bool sign;

    rationalNumber(const int n = 0) : numerator(std::abs(n)), denominator(1), sign(std::signbit(n)) {}
    rationalNumber(const T n, const T d, const bool s = false) : numerator(n), denominator(d), sign(s) {}
    rationalNumber(const rationalNumber&) = default;
    rationalNumber& operator=(const rationalNumber&) = default;

    rationalNumber operator-() const
    {
        return rationalNumber(numerator, denominator, !sign);
    }

    void reduce()
    {
        T divisor = gcd(numerator, denominator);
        if (divisor != 1)
        {
            numerator /= divisor;
            denominator /= divisor;
        }
        else if (numerator == 0)
        {
            denominator = 1;
            sign = false;
        }

        assert(denominator != 0);
    }
};

using RN = rationalNumber<unsigned long long>;

Is it feasible to implement the remaining relational operators operators (<, >, <=, >=) using floating point arithmetic, or will that lead to error prone results?

Note that I have only considered floating points since cross multiplying could in many cases lead to integer overflow.


Solution

  • Yes, it is feasible to implement the test for inequality using floating point operations. And, yes, that will potentially give "error prone results" due to finite precision of floating point.

    It is not actually necessary to use floating point at all. Mathematically, a test of "a/b > c/d" (assuming a,b,c,d are positive) is equivalent to the test "ad > bc". With unsigned variables, you will also need to account for (or work around) the effects of modulo arithmetic (I'll leave doing that as an exercise) but it is quite feasible to implement the test exactly without using floating point at all.