#include "frac.h" #include #include #ifdef DEBUG #include using std::cerr; using std::endl; #endif Fraction::~Fraction() { cerr << "Destroying fraction " << N << "/" << D << " at " << (void*)this << endl; } #define CHECK_DENOMINATOR if ( D == 0 ) throw std::runtime_error("Division by zero"); int gcd(int x, int y) { // special cases if ( y>x ) return gcd(y,x); if (y<0) return gcd(-y,0); // default case: x>=y>0 int z; while (y) { z=y; y=x%y; x=z; } return x; } Fraction::Fraction(int N, int D) :N(N),D(D) { CHECK_DENOMINATOR simplify(); } Fraction::operator double() { return N/static_cast(D); } int Fraction::numerator() const { return N; } int Fraction::denominator() const { return D; } Fraction::Fraction(const Fraction& rhs) :N(rhs.N),D(rhs.D) { } Fraction Fraction::reciprocal() const { CHECK_DENOMINATOR return Fraction(D,N); } Fraction& Fraction::operator=(const Fraction& rhs) { D=rhs.D; N=rhs.N; return *this; } Fraction& Fraction::operator+= ( const Fraction& right) { N = N * right.D + right.N * D; D *= right.D; simplify(); return *this; } Fraction& Fraction::operator+= (int right) { return (*this) += Fraction(right,1); } Fraction& Fraction::operator-= (const Fraction& right) { return *this+=( (-1) * right); } Fraction& Fraction::operator-= (int right) { return (*this) += Fraction(-right,1); } Fraction& Fraction::operator*= (const Fraction& right) { N*=right.N; D*=right.D; simplify(); return *this; } Fraction& Fraction::operator*= (int right) { return (*this) *= Fraction(right,1); } Fraction& Fraction::operator/= (const Fraction& right) { N*=right.D; D*=right.N; CHECK_DENOMINATOR simplify(); return *this; } Fraction& Fraction::operator/= (int right) { return (*this) /= Fraction (1,right); } Fraction operator+ (const Fraction& left, const Fraction& right) { return Fraction(left) += right; } Fraction operator+ (const Fraction& f, int i) { return Fraction(f)+=i; } Fraction operator+ (int i, const Fraction& f) { return Fraction(f)+=i; } Fraction operator- (const Fraction& left, const Fraction& right) { return Fraction(left) -= right; } Fraction operator- (const Fraction& f, int i) { return Fraction(f)-=i; } Fraction operator- (int i, const Fraction& f) { return Fraction(f)-=i; } Fraction operator* (const Fraction& left, const Fraction& right) { return Fraction(left) *= right; } Fraction operator*(const Fraction& f, int i) { return Fraction(f)*= i; } Fraction operator*(int i, const Fraction& f ) { return Fraction(f)*= i; } Fraction operator/ (const Fraction& left, const Fraction& right) { return left * right.reciprocal(); } Fraction operator/(const Fraction& f, int i) { return Fraction(f)/= i; } Fraction operator/(int i, const Fraction& f ) { return Fraction(f)/= i; } void Fraction::simplify() { int tmp = gcd(N,D); N /= tmp; D /= tmp; } std::string Fraction::toString() { std::ostringstream out; out << numerator() << "/" << denominator(); return out.str(); }