//by Curtis Michels
//main.cpp
#include <iostream>
#include "Rationals.h"
using namespace std;
void test() {
Rational x{-1,2};
Rational y{5};
cout << x.toString() << endl;
cout << y.toString() << endl;
Rational z{x+y};
cout << "x + y = " << z.toString() << endl;
cout << "x - y = " << (x-y).toString() << endl;
}
void test2() {
cout << GCD(54,888);
}
void test3() {
Rational x{2,4};
Rational y{1,8};
cout << "x + y = " << (x+y).toString() << endl;
cout << "x * y = " << (x*y).toString() << endl;
cout << "x / y = " << (x/y).toString() << endl;
}
void test4() {
Rational x{2,4};
Rational y{2,4};
Rational z{2,6};
Rational g{4,8};
Rational h{1};
cout << "x " << x << endl;
cout << "y " << y << endl;
cout << "z " << z << endl;
cout << "g " << g << endl;
cout <<endl;
cout << (x == y) << endl;
cout << (x == z) << endl;
cout << endl;
cout << (x == g) << endl;
cout << (x != y) << endl;
cout << (x != z) << endl;
cout << (x != g) << endl;
cout << endl;
cout << (x<h) << endl;
cout << (x>h) << endl;
cout << (x>y) << endl;
cout << (x<y) << endl;
cout << endl;
cout << (x<=h) << endl;
cout << (x>=h) << endl;
cout << (x>=y) << endl;
cout << (x<=y) << endl;
}
int main()
{
test();
test2();
test3();
test4();
return 0;
}
//by Curtis Michels
//Rationals.h
#ifndef RATIONALS_H
#define RATIONALS_H
#include <iostream>
#include <sstream>
#include <vector>
#include <math.h>
#include <stdexcept>
int GCD(const int, const int); //returns greatest common divisor between two numbers
class Rational {
friend std::ostream& operator<<(std::ostream&,const Rational);
public:
Rational(); //default constructor, defaults to a numerator of 0 and denominator of 1
Rational(const int Numerator, const int Denominator); //constructor that takes ints for the num/denom
Rational(const int Numerator); //constructor that only takes numerator, default denominator is 1
int getNumerator(); //returns numerator
int getDenominator(); //returns denominator
void setNumerator(const int); //sets numerator, can be <= 0
void setDenominator(const int); //sets denominator, must be > 0
std::string toString(); //outputs the rational number as a string
Rational reduce(); //reduces the fraction, keeping the correct sign
Rational operator+(const Rational); //properly adds two rational numbers
Rational operator-(const Rational); //properly subtracts two rational numbers
Rational operator*(const Rational); //multiplies two rationals
Rational operator/(const Rational); //divides two rationals
bool operator==(const Rational); //checks if two rationals are the same
bool operator!=(const Rational); //checks if two rationals are not the same
bool operator<(const Rational); //checks if a rational is less than another
bool operator>(const Rational); //checks if a rational is bigger than another
bool operator<=(const Rational); //checks if a rational is less than or equal to another
bool operator>=(const Rational); //checks if a rational is large than or equal to another
private:
int numerator{}; //can be any integer
int denominator{}; //cannot be <= 0
};
#endif // RATIONALS_H
//by Curtis Michels
//Rationals.cpp
#include "Rationals.h"
Rational::Rational():numerator{0}, denominator{1}{ //default constructor, initializes fraction to 0
}
Rational::Rational(int inNumerator, int inDenominator){ //constructor that takes in two ints
setNumerator(inNumerator);
setDenominator(inDenominator);
}
Rational::Rational(int inNumerator){ //constructor that takes in just the numerator
setNumerator(inNumerator);
setDenominator(1);
}
std::ostream& operator<<(std::ostream& oin,Rational in) { //overloads left shift operator to work with cout and similar, depends on toString function
std::cout << in.toString();
return oin;
}
int Rational::getNumerator() { //returns numerator
return numerator;
}
int Rational::getDenominator() { //returns denominator
return denominator;
}
void Rational::setNumerator(int in) { //sets numerator, can be anything including <= 0
numerator = in;
}
void Rational::setDenominator(int in) { //sets denominator, must be > 0
if (in > 0) {
denominator = in;
}
else{
throw std::invalid_argument("Denominator must be > 0");
}
}
std::string Rational::toString() { //returns a string with numerator and denominator separated by a slash
std::stringstream result;
result << getNumerator() << "/" << getDenominator();
return result.str();
}
Rational Rational::reduce() { //reduces fraction by finding and dividing both numerator and denominator by greatest common factor
Rational result{};
int gcd = GCD(getNumerator(),getDenominator());
result.setNumerator(getNumerator()/gcd);
result.setDenominator(getDenominator()/gcd);
return result;
}
int GCD(int in1, int in2) { //finds greatest common factor via recursive Euclidian Algorithm, non-member function
if (in1 < 0) { in1 = in1 * -1;} //this line ensures it always returns a positive number
if (in1 == in2) {return in1;} //doesn't bother doing anything more if both inputs are equal
int result{};
int divisor{};
int remainder{};
if(in1 > in2) {
divisor = in2;
remainder = in1%in2;
}
else {
divisor = in1;
remainder = in2%in1;
}
if (remainder == 0) {result = divisor;}
else {result = GCD(divisor,remainder);}
return result;
}
Rational Rational::operator+(Rational in) { //adds and returns two rational numbers, reduces to most simplified form
Rational result{};
result.setNumerator(this->getNumerator() * in.getDenominator() + in.getNumerator() * this->getDenominator());
result.setDenominator(this->getDenominator() * in.getDenominator());
return result.reduce();
}
Rational Rational::operator-(Rational in) { //subtracts and returns two rational numbers (Depends on + overloaded operator), reduces to most simplified form
Rational result{};
result.setNumerator(-1 * in.getNumerator());
result.setDenominator(in.getDenominator());
return (*this+result);
}
Rational Rational::operator*(Rational in) { //multiplies two fractions, reduces to most simplified form
Rational result{};
result.setNumerator(this->getNumerator() * in.getNumerator());
result.setDenominator(this->getDenominator() * in.getDenominator());
return result.reduce();
}
Rational Rational::operator/(Rational in) { //divides two rational numbers, reduces to most simplified form, will throw an error if you try to divide by 0
Rational result{};
result.setNumerator(in.getDenominator()); //these two lines flip the numerator and denominator so we can multiply by the reciprocal
result.setDenominator(in.getNumerator());
result = result * *this;
}
bool Rational::operator==(Rational in) { //compares if two rational numbers are the same, (reduces both to most simplified form BEFORE comparing)
bool result{false};
if (this->reduce().getNumerator() == in.reduce().getNumerator() && this->reduce().getDenominator() == in.reduce().getDenominator()) {result = true;}
return result;
}
bool Rational::operator!=(Rational in) {
bool result{!(*this==in)};
return result;
}
bool Rational::operator<(Rational in) { //checks if a rational is less than another
bool result{false};
double compare1{this->getNumerator()/this->getDenominator()};
double compare2{in.getNumerator()/in.getDenominator()};
if (compare1 < compare2) {result = true;}
return result;
}
bool Rational::operator>(const Rational in) { //checks if a rational is bigger than another
bool result{false};
if (*this != in) { result = !(*this<in); }
return result;
}
bool Rational::operator<=(Rational in) { //checks if a rational is less than or = to another
bool result{false};
double compare1{this->getNumerator()/this->getDenominator()};
double compare2{in.getNumerator()/in.getDenominator()};
if (compare1 <= compare2) {result = true;}
return result;
}
bool Rational::operator>=(const Rational in) { //checks if a rational is bigger than or = to another
bool result{false};
result = !(*this<in);
return result;
}