#include "Rational.hpp" #include #include ///////////////////////////////////////////////// // This file contains all function definitions // // - All function declarations are in // // the file Rational.hpp // ///////////////////////////////////////////////// //////////////////////// // Helper function // //////////////////////// // NEW: Calculate the greatest common divisor of m and n. // // This is a private static member function because it is // used internally by the Rational class, but does not // require a particular Rational object. int Rational::gcd( int m, int n ) { m = std::abs( m ); n = std::abs( n ); while ( n != 0 ) { int remainder{ m%n }; m = n; n = remainder; } return m; } ////////////////// // Constructor // ////////////////// // NEW: Construct a rational number in normal form. // // The denominator must be nonzero. If it is negative, // move the negative sign to the numerator. Then divide // the numerator and denominator by their greatest common // divisor. // // Consequently, once a Rational object has been // constructed: // // denominator_ > 0 // // and the numerator and denominator have no common // divisor greater than one. Rational::Rational( int const numerator, int const denominator ): numerator_{ numerator }, denominator_{ denominator } { assert( denominator_ != 0 ); if ( denominator_ < 0 ) { numerator_ = -numerator_; denominator_ = -denominator_; } int divisor{ gcd( numerator_, denominator_ ) }; numerator_ /= divisor; denominator_ /= divisor; } //////////////////////// // Query functions // //////////////////////// // NEW: Return the numerator. int Rational::numer() const { return numerator_; } // NEW: Return the denominator. int Rational::denom() const { return denominator_; } ////////////////////////// // Arithmetic operators // ////////////////////////// // Calculate this + q. Rational Rational::operator+( Rational const &q ) const { return Rational{ numerator_*q.denominator_ + q.numerator_*denominator_, denominator_*q.denominator_ }; } // Calculate this + n. Rational Rational::operator+( int const n ) const { return *this + Rational{ n }; } // Calculate n + p. // // This cannot be a member function of Rational because // the left operand is an int. Rational operator+( int const n, Rational const &p ) { return p + n; } // Calculate this - q. Rational Rational::operator-( Rational const &q ) const { return *this + (-q); } // Calculate this - n. Rational Rational::operator-( int const n ) const { return *this + (-n); } // Calculate n - p. // // This cannot be a member function of Rational because // the left operand is an int. Rational operator-( int const n, Rational const &p ) { return Rational{ n } - p; } // Calculate this*q. Rational Rational::operator*( Rational const &q ) const { return Rational{ numerator_*q.numerator_, denominator_*q.denominator_ }; } // Calculate this*n. Rational Rational::operator*( int const n ) const { return *this * Rational{ n }; } // Calculate n*p. // // This cannot be a member function of Rational because // the left operand is an int. Rational operator*( int const n, Rational const &p ) { return p*n; } // Calculate this/q. Rational Rational::operator/( Rational const &q ) const { assert( q.numerator_ != 0 ); return *this * q.inverse(); } // Calculate this/n. Rational Rational::operator/( int const n ) const { assert( n != 0 ); return *this / Rational{ n }; } // Calculate n/p. // // This cannot be a member function of Rational because // the left operand is an int. Rational operator/( int const n, Rational const &p ) { return Rational{ n }/p; } ////////////////////// // Unary operators // ////////////////////// // Return this rational number unchanged. Rational Rational::operator+() const { return *this; } // Return the additive inverse of this rational number. Rational Rational::operator-() const { return Rational{ -numerator_, denominator_ }; } ////////////////////////// // Rational operations // ////////////////////////// // Return the multiplicative inverse. // // Zero does not have a multiplicative inverse. Rational Rational::inverse() const { assert( numerator_ != 0 ); return Rational{ denominator_, numerator_ }; } // Return the absolute value. Rational Rational::abs() const { return Rational{ std::abs( numerator_ ), denominator_ }; } // Return the value as a double. double Rational::real() const { return static_cast( numerator_ )/denominator_; } ////////////////////////// // Comparison operators // ////////////////////////// // Determine whether this == q. // // Since every Rational object is stored in normal form, // equal rational numbers have identical numerators and // denominators. bool Rational::operator==( Rational const &q ) const { return (numerator_ == q.numerator_) && (denominator_ == q.denominator_); } // Determine whether this == n. bool Rational::operator==( int const n ) const { return *this == Rational{ n }; } // Determine whether n == p. bool operator==( int const n, Rational const &p ) { return p == n; } // Determine whether this != q. bool Rational::operator!=( Rational const &q ) const { return !(*this == q); } // Determine whether this != n. bool Rational::operator!=( int const n ) const { return !(*this == n); } // Determine whether n != p. bool operator!=( int const n, Rational const &p ) { return p != n; } // Determine whether this < q. bool Rational::operator<( Rational const &q ) const { return numerator_*q.denominator_ < q.numerator_*denominator_; } // Determine whether this < n. bool Rational::operator<( int const n ) const { return *this < Rational{ n }; } // Determine whether n < p. bool operator<( int const n, Rational const &p ) { return Rational{ n } < p; } // Determine whether this <= q. bool Rational::operator<=( Rational const &q ) const { return (*this < q) || (*this == q); } // Determine whether this <= n. bool Rational::operator<=( int const n ) const { return *this <= Rational{ n }; } // Determine whether n <= p. bool operator<=( int const n, Rational const &p ) { return Rational{ n } <= p; } // Determine whether this >= q. bool Rational::operator>=( Rational const &q ) const { return !(*this < q); } // Determine whether this >= n. bool Rational::operator>=( int const n ) const { return *this >= Rational{ n }; } // Determine whether n >= p. bool operator>=( int const n, Rational const &p ) { return Rational{ n } >= p; } // Determine whether this > q. bool Rational::operator>( Rational const &q ) const { return !(*this <= q); } // Determine whether this > n. bool Rational::operator>( int const n ) const { return *this > Rational{ n }; } // Determine whether n > p. bool operator>( int const n, Rational const &p ) { return Rational{ n } > p; } /////////////////////////// // Output and conversion // /////////////////////////// // Return a string representation of this rational number. std::string Rational::to_string() const { if ( denominator_ == 1 ) { return std::to_string( numerator_ ); } return std::to_string( numerator_ ) + "/" + std::to_string( denominator_ ); } // Insert p into an output stream. // // This remains a free function because the left operand // of << is the output stream rather than the Rational // object. std::ostream &operator<<( std::ostream &out, Rational const &p ) { out << p.to_string(); return out; }