`

      1  #include "fraction.h"
      2  #include <cassert>
      3  #include <stdexcept>
      4
      5  int Fraction::gcd(int n, int m)
      6  {
      7     // Euclid's Greatest Common Divisor algorithm.
      8     assert((n > 0) && (m > 0));
      9     while (n != m)
     10     {
     11        if (n < m)
     12           m = m - n;
     13        else
     14           n = n - m;
     15     }
     16     return n;
     17  }
     18
     19  Fraction::Fraction(int t, int b) : top(t), bottom(b)
     20  {
     21     normalize();
     22  }
     23
     24  Fraction::Fraction() : top(0), bottom(1) {}
     25
     26  Fraction::Fraction(int t) : top(t), bottom(1) {}
     27
     28  int Fraction::numerator() const
     29  {
     30     return top;
     31  }
     32
     33  int Fraction::denominator() const
     34  {
     35     return bottom;
     36  }
     37
     38  void Fraction::normalize()
     39  {
     40     // Normalize fraction by
     41     // (a) moving sign to numerator
     42     // (b) ensuring numerator and denominator have no common divisors
     43     int sign = 1;
     44     if (top < 0)
     45     {
     46        sign = -1;
     47        top = -top;
     48     }
     49     if (bottom < 0)
     50     {
     51        sign = -sign;
     52        bottom = -bottom;
     53     }
     54     assert(bottom != 0)
     55     int d = 1;
     56     if (top > 0) d = gcd(top, bottom);
     57     top = sign * (top / d);
     58     bottom = bottom / d;
     59  }
     60
     61  Fraction operator+(const Fraction& left, const Fraction& right)
     62  {
     63     Fraction result(left.numerator() * right.denominator()
     64        + right.numerator() * left.denominator(),
     65        left.denominator() * right.denominator());
     66     return result;
     67  }
     68
     69  Fraction operator-(const Fraction& left, const Fraction& right)
     70  {
     71     Fraction result(left.numerator() * right.denominator()
     72        - right.numerator() * left.denominator(),
     73        left.denominator() * right.denominator());
     74     return result;
     75  }
     76
     77  Fraction operator*(const Fraction& left, const Fraction& right)
     78  {
     79     Fraction result(left.numerator() * right.numerator(),
     80        left.denominator() * right.denominator());
     81     return result;
     82  }
     83
     84  Fraction operator/(const Fraction& left, const Fraction& right)
     85  {
     86     Fraction result(left.numerator() * right.denominator(),
     87        left.denominator() * right.numerator());
     88     return result;
     89  }
     90
     91  Fraction operator-(const Fraction& value)
     92  {
     93     Fraction result(-value.numerator(), value.denominator());
     94     return result;
     95  }
     96
     97  int Fraction::compare(const Fraction& right) const
     98  {
     99     return numerator() * right.denominator()
    100     - denominator() * right.numerator();
    101     // Return the numerator of the difference
    102  }
    103
    104  bool operator<(const Fraction& left, const Fraction& right)
    105  {
    106     return left.compare(right) < 0;
    107  }
    108
    109  bool operator<=(const Fraction& left, const Fraction& right)
    110  {
    111     return left.compare(right) <= 0;
    112  }
    113
    114  bool operator==(const Fraction& left, const Fraction& right)
    115  {
    116     return left.compare(right) == 0;
    117  }
    118
    119  bool operator!=(const Fraction& left, const Fraction& right)
    120  {
    121     return left.compare(right) != 0;
    122  }
    123
    124  bool operator>=(const Fraction& left, const Fraction& right)
    125  {
    126     return left.compare(right) >= 0;
    127  }
    128
    129  bool operator>(const Fraction& left, const Fraction& right)
    130  {
    131     return left.compare(right) > 0;
    132  }
    133
    134  ostream& operator<<(ostream& out, const Fraction& value)
    135  {
    136     out << value.numerator() << "/" << value.denominator();
    137     return out;
    138  }
    139
    140  istream& operator>>(istream& in, Fraction& r)
    141  {
    142     int t, b;
    143     // Read the top
    144     in >> t;
    145     // If there is a slash, read the next number
    146     char c;
    147     in >> c;
    148     if (c == '/')
    149        in >> b;
    150     else
    151     {
    152        in.putback(c);
    153        b = 1;
    154     }
    155     r = Fraction(t, b);
    156     return in;
    157  }
    158
    159  Fraction::operator double() const
    160  {
    161     // Convert numerator to double, then divide
    162     return static_cast<double>(top) / bottom;
    163  }
    164
    165  Fraction& Fraction::operator++()
    166  {
    167     top += bottom;
    168     return *this;
    169  }
    170
    171  Fraction Fraction::operator++(int unused)
    172  {
    173     Fraction clone(top, bottom);
    174     top += bottom;
    175     return clone;
    176  }
    177
    178  Fraction& Fraction::operator+=(const Fraction& right)
    179  {
    180     top = top * right.denominator() + bottom * right.numerator();
    181     bottom *= right.denominator();
    182     normalize();
    183     return *this;
    184  }

`