//--------------------------------------------------------- // File: RationalTestProg.cpp // // Purpose: Test the rational class member functions and // operators. // // D. Searls // Asbury College // Feb 2002 //--------------------------------------------------------- #include <iostream> #include <iomanip> #include <cmath> using namespace std; class rational { private: long n; // numerator long d; // denominator public: // Class constructors //--------------------------------------------------------- // Default constructor creates a new rational with a value // of 0/1. //--------------------------------------------------------- rational() { n = 0; d = 1; } //--------------------------------------------------------- // Initialization constructor creates a new rational with // a value of numer/denom. // // Precondition: denom != 0 // // In Parameters: numer, denom //--------------------------------------------------------- rational(long numer, long denom) { init(numer, denom); } //--------------------------------------------------------- // Copy constructor creates a new rational that has the // same value as r. // // In Parameter: r //--------------------------------------------------------- rational(const rational& r) { n = r.n; d = r.d; } // Member functions //--------------------------------------------------------- // Reduce a rational to lowest terms // // This function is not part of the public interface. //--------------------------------------------------------- void reduce() { long gcd = abs(n); long y = abs(d); long temp; if (d == 0) { return; } // 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; } } //--------------------------------------------------------- // Convert a rational to the nearest integer value and // return that value //--------------------------------------------------------- long 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; } //--------------------------------------------------------- // Convert a rational to a decimal value and return it //--------------------------------------------------------- double toReal() const { return double(n)/double(d); } //--------------------------------------------------------- // Initalize this rational to the value numer/denom. // // Precondition: denom != 0 // // In Parameters: numer, denom //--------------------------------------------------------- void init(long numer, long denom) { n = numer; d = denom; reduce(); } //--------------------------------------------------------- // Return sum of two rationals (this + r) //--------------------------------------------------------- rational add(rational r) const { rational sum; if (d == r.d) { sum.init(n + r.n, d); } else { sum.init(n*r.d + d*r.n, d*r.d); } sum.reduce(); return sum; } //--------------------------------------------------------- // Return difference of two rationals (this - r) //--------------------------------------------------------- rational sub(rational r) const { rational diff(n*r.d - d*r.n, d*r.d); diff.reduce(); return diff; } //--------------------------------------------------------- // Return product of two rationals (this*r) //--------------------------------------------------------- rational mul(rational r) const { rational prod(n*r.n, d*r.d); prod.reduce(); return prod; } //--------------------------------------------------------- // Return quotient of two rationals (this/r) //--------------------------------------------------------- rational div(rational r) const { rational quotient(n*r.d, d*r.n); quotient.reduce(); return quotient; } //--------------------------------------------------------- // Assign the value of the rational parameter to this // rational and return that value as the return value of // this function. //--------------------------------------------------------- rational assign(rational r) { n = r.n; d = r.d; return r; } //--------------------------------------------------------- // Compare two rationals // // If (this < r) // return a negative value // else if (this == r) // return zero // else // return a positive value //--------------------------------------------------------- long compare(rational r) const { return (n*r.d - d*r.n); } //--------------------------------------------------------- // Input a rational value from the keyboard as "n/d" where // n and d are integer values. // // It is assumed that the denominator will not be zero. //--------------------------------------------------------- void input() { char slash; cin >> n; // Read the numerator cin >> slash; // Read the divide symbol cin >> d; // Read the denominator reduce(); } //--------------------------------------------------------- // Output a rational value to cout as "n/d" where // n and d are integer values. If the denominator is zero, // the text "NaR" (Not a Rational) will be displayed. //--------------------------------------------------------- void output() const { if (d == 0) { cout << "NaR"; } else { cout << n << '/' << d; } } }; //--------------------------------------------------------- // T E S T P R O G R A M //--------------------------------------------------------- int main() { rational r1; rational r2(6,8); rational r3(r2); // Verify constructors and output member function cout << "Default Constructor: r1 = "; r1.output(); cout << endl; cout << "You SHOULD get: r1 = 0/1\n\n"; cout << "Initialization Constructor: r2 = "; r2.output(); cout << endl; cout << "You SHOULD get: r2 = 3/4\n\n"; cout << "Copy Constructor: r3 = "; r3.output(); cout << endl; cout << "You SHOULD get: r3 = 3/4\n\n"; // Test Input cout << "Enter a rational in the form a/b: "; r3.input(); cout << "You entered: "; r3.output(); cout << endl << endl; // Test arithmetic operators r1 = r2.add(r3); r2.output(); cout << " + "; r3.output(); cout << " = "; r1.output(); cout << endl; r1 = r2.sub(r3); r2.output(); cout << " - "; r3.output(); cout << " = "; r1.output(); cout << endl; r1 = r2.mul(r3); r2.output(); cout << " * "; r3.output(); cout << " = "; r1.output(); cout << endl; r1 = r2.div(r3); r2.output(); cout << " / "; r3.output(); cout << " = "; r1.output(); cout << endl << endl; // Test init r1.init(34,20); cout << "After r1.init(34,20) r1 = "; r1.output(); cout << endl; cout << "You SHOULD have gotten r1 = 17/10\n"; r1.init(12,-31); cout << "After r1.init(12,-31) r1 = "; r1.output(); cout << endl; cout << "You SHOULD have gotten r1 = -12/31\n\n"; // Test assignment r3.assign(r2.assign(r1)); cout << "After r3.assign(r2.assign(r1)) r2 = "; r2.output(); cout << endl; cout << " r3 = "; r3.output(); cout << endl; cout << "Both r2 and r3 SHOULD equal r1: r1 = -12/31\n\n"; // Test compare r1.init(1, 2); r2.init(1, 3); r1.output(); cout << ".compare("; r2.output(); cout << ") = " << r1.compare(r2) << endl; r2.output(); cout << ".compare("; r1.output(); cout << ") = " << r2.compare(r1) << endl; r1.output(); cout << ".compare("; r1.output(); cout << ") = " << r1.compare(r1) << endl; cout << endl; // Test conversion functions cout << fixed << setprecision(10); r1.init(9, 5); r2.init(-100, 3); r1.output(); cout << " to the nearest integer is " << r1.toInt() << endl; r1.output(); cout << " as a real is " << r1.toReal() << endl; r2.output(); cout << " to the nearest integer is " << r2.toInt() << endl; r2.output(); cout << " as a real is " << r2.toReal() << endl; cout << endl; //r1.reduce(); // Trying to access a private member function //r1.n = 3; // or private data members results in compile //r1.d = 4; // errors. return 0; }