header
//---------------------------------------------------------
// rational.h
//
// Declarations for a better rational class
//
// D Searls
// Asbury College
// Feb 2002
//---------------------------------------------------------
#ifndef RATIONAL_H
#define RATIONAL_H
#include <iostream>
using namespace std;

// Declaration section

class rational
{
public:

    // Class constructors
    
    rational();
    rational(long numer, long denom);
    rational(const rational &r);
    
    // Member functions
    
private:
    void reduce();
    
public:
    long toInt() const;
    double toReal() const;
    void init(long numer, long denom);
    
    // Member operations
    
public:

    rational operator + (const rational &r) const;
    rational operator - (const rational &r) const;
    rational operator * (const rational &r) const;
    rational operator / (const rational &r) const;
    rational& operator = (const rational &r);
    bool operator == (const rational &r) const;
    bool operator <  (const rational &r) const;
    bool operator >  (const rational &r) const;
    bool operator <= (const rational &r) const;
    bool operator >= (const rational &r) const;
    bool operator != (const rational &r) const;
    friend istream& operator >> (istream &is, rational &r);
    friend ostream& operator << (ostream &os, const rational &r);
    
private:

    // Data members

    long n, d;   // numerator and denominator
};
#endif
//---------------------------------------------------------
// rational.cpp
//
// Implementation of a better rational class.
//
// D Searls
// Asbury College
// Feb 2002
//---------------------------------------------------------
#include "rational.h"
#include <cmath>

// Class constructors

rational::rational()
{
    n = 0;
    d = 1;
}

rational::rational(long numer, long denom)
{
    n = numer;
    d = denom;
    reduce();
}

rational::rational(const rational &r)
{
    n = r.n;
    d = r.d;
}

// Member functions

void rational::reduce()
{
    long gcd = abs(n);
    long y = abs(d);
    long temp;
    // Make sure gcd is initalized as larger of two values
    if (gcd < y)
    {
        temp = gcd;
        gcd = y;
        y = temp;
    }
    // Find the gcd
    while (y != 0)
    {
        temp = gcd % y;
        gcd = y;
        y = temp;
    }
    // Reduce the fraction
    n = n / gcd;
    d = d / gcd;
    // Make sure denominator is positive
    if (d < 0)  // In a reduced fraction, denominator > 0
    {
        d = -d;
        n = -n;
    }
}

long rational::toInt() const
{
    bool isNegative;
    double num;
    long intValue;
    isNegative = (n < 0);
    num = double(n)/double(d);
    if (isNegative) {
        num = -num;
    }
    intValue = long(num + 0.5);
    if (isNegative) {
        intValue = -intValue;
    }
    return intValue;
}

double rational::toReal() const
{
    return double(n)/double(d);
}

void rational::init(long numer, long denom)
{
    n = numer;
    d = denom;
    reduce();
}

// Member operations

rational rational::operator + (const rational &r) const
{
    long numerator = n*r.d + d*r.n;
    long denominator = d*r.d;
    rational sum(numerator, denominator);
    return sum;
}

rational rational::operator - (const rational &r) const
{
    long numerator = n*r.d - d*r.n;
    long denominator = d*r.d;
    rational diff(numerator, denominator);
    return diff;
}

rational rational::operator * (const rational &r) const
{
    long numerator = n*r.n;
    long denominator = d*r.d;
    rational prod(numerator, denominator);
    return prod;
}

rational rational::operator / (const rational &r) const
{
    long numerator = n*r.d;
    long denominator = d*r.n;
    rational quotient(numerator, denominator);
    return quotient;
}

rational& rational::operator = (const rational &r)
{
    n = r.n;
    d = r.d;
    return *this;
}

bool rational::operator == (const rational &r) const
{
    return (n*r.d == d*r.n);
}

bool rational::operator < (const rational &r) const
{
    return (n*r.d < d*r.n);
}

bool rational::operator > (const rational &r) const
{
    return (n*r.d > d*r.n);
}

bool rational::operator <= (const rational &r) const
{
    return (n*r.d <= d*r.n);
}

bool rational::operator >= (const rational &r) const
{
    return (n*r.d >= d*r.n);
}

bool rational::operator != (const rational &r) const
{
    return (n*r.d != d*r.n);
}

istream& operator >> (istream &is, rational &r)
{
    char slash;
    is >> r.n;     // Read the numerator
    is >> slash;   // Read the divide symbol
    is >> r.d;     // Read the denominator
    r.reduce();
    return is;
}

ostream& operator << (ostream &os, const rational &r)
{
    os << r.n << '/' << r.d;
    return os;
}