// // Program name: test_rationals_v1 // Author: B. Massingill // // Purpose: test RationalNum class (version 1) // #include // -------- definition of class for rational numbers -------- // // an object of this class represents a rational number, i.e., a // fraction // class RationalNum { private: // ---- member variables ---- int numerator; int denominator; public: // ---- constructors ---- RationalNum(const int n=0, const int d=1); // ---- member functions ---- // read from input stream // precondition: iStr is an input stream (already successfully // opened if an ifstream) // postcondition: // if iStr contains a fraction in the form integer/integer, // that fraction is read in and return value is true // otherwise return value is false bool stream_in(istream& iStr); // print to output stream // precondition: oStr is an output stream (already successfully // opened if an ofstream) // postcondition: fraction has been printed on oStr, in the form // numerator/denominator void stream_out(ostream& oStr); // "reduce" to simplest terms // precondition: none // postcondition: denominator is non-negative, numerator and // denominator have no common factors void reduce(void); // ---- friend functions ---- // comparison functions // precondition: none // postcondition: return value indicates whether p == q // (for equals), p < q (for lessThan), or p > q (for // greaterThan) friend bool equals(const RationalNum p, const RationalNum q); friend bool lessThan(const RationalNum p, const RationalNum q); friend bool greaterThan(const RationalNum p, const RationalNum q); // arithmetic functions // precondition: none // postcondition: return value is p+q, p-q, p*q, p/q as // indicated by function name friend RationalNum add(const RationalNum p, const RationalNum q); friend RationalNum subtract(const RationalNum p, const RationalNum q); friend RationalNum multiply(const RationalNum p, const RationalNum q); friend RationalNum divide(const RationalNum p, const RationalNum q); } ; // -------- helper functions for RationalNum -------- // function to compute greatest common divisor // precondition: m, n are positive numbers // postcondition: return value is the greatest common divisor of m, n int gcd(int m, int n); // -------- additional functions for test program -------- // precondition: // postcondition: functions of RationalNum class have been tested, // using p and q void testRationalNum(RationalNum p, RationalNum q); // precondition: // postcondition: p has been printed to cout, preceded by msg and // followed by end-of-line void printIt(const char msg[], RationalNum p); // -------- main program -------- int main() { char prompt1[] = "Enter first number, in the form m/n, " "or ctrl-D to end: "; char prompt2[] = "Enter second number, in the form m/n: "; RationalNum p; RationalNum q; cout << prompt1; while (p.stream_in(cin)) { cout << prompt2; q.stream_in(cin); testRationalNum(p, q); cout << prompt1; } cout << endl; return 0 ; } // -------- functions for test program -------- void testRationalNum(RationalNum p, RationalNum q) { printIt("p = ", p); printIt("q = ", q); p.reduce(); q.reduce(); // test comparisons if (equals(p, q)) cout << "p == q" << endl; if (lessThan(p, q)) cout << "p < q" << endl; if (greaterThan(p, q)) cout << "p > q" << endl; // test reduce printIt("reduced p = ", p); printIt("reduced q = ", q); // test arithmetic functions printIt("p + q = ", add(p, q)); printIt("p - q = ", subtract(p, q)); printIt("p * q = ", multiply(p, q)); printIt("p / q = ", divide(p, q)); return; } void printIt(const char msg[], RationalNum p) { cout << msg; p.stream_out(cout); cout << endl; return; } // -------- functions for RationalNum class -------- // ---- constructors ---- RationalNum::RationalNum(const int n=0, const int d=1) { numerator = n; denominator = d; } // ---- member functions ---- bool RationalNum::stream_in(istream& iStr) { int n, d; char c; iStr >> n >> c >> d; if (iStr && (c == '/')) { numerator = n; denominator = d; return true; } else return false; } void RationalNum::stream_out(ostream& oStr) { oStr << numerator << "/" << denominator; return; } void RationalNum::reduce(void) { int divisor; if (denominator == 0) numerator = 1; else if (numerator == 0) denominator = 1; else { if (denominator < 0) { denominator *= -1; numerator *= -1; } divisor = gcd(abs(numerator), denominator); numerator /= divisor; denominator /= divisor; } return; } // ---- friend functions ---- bool equals(const RationalNum p, const RationalNum q) { return (p.numerator*q.denominator) == (q.numerator*p.denominator); } bool lessThan(const RationalNum p, const RationalNum q) { return (p.numerator*q.denominator) < (q.numerator*p.denominator); } bool greaterThan(const RationalNum p, const RationalNum q) { return (p.numerator*q.denominator) > (q.numerator*p.denominator); } RationalNum add(const RationalNum p, const RationalNum q) { RationalNum r = RationalNum( p.numerator*q.denominator + q.numerator*p.denominator, p.denominator*q.denominator); r.reduce(); return r; } RationalNum subtract(const RationalNum p, const RationalNum q) { RationalNum r = RationalNum( p.numerator*q.denominator - q.numerator*p.denominator, p.denominator*q.denominator); r.reduce(); return r; } RationalNum multiply(const RationalNum p, const RationalNum q) { RationalNum r = RationalNum(p.numerator*q.numerator, p.denominator*q.denominator); r.reduce(); return r; } RationalNum divide(const RationalNum p, const RationalNum q) { RationalNum r = RationalNum(p.numerator*q.denominator, p.denominator*q.numerator); r.reduce(); return r; } // ---- "helper functions" ---- int gcd(int m, int n) // use Euclid's algorithm for finding greatest common divisor // depends on two observations: // if m is a multiple of n, gcd(m, n) == n // otherwise, can write m = nt + r, and gcd(m, n) == gcd(n, r) { int r; // ensure that m >= n if (m < n) { int temp = m; m = n; n = temp; } do { r = m % n; m = n; n = r; } while (r != 0); return m; }