﻿ Classes
```//---------------------------------------------------------
// 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

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;
}```