This commit is contained in:
Sandipsinh Rathod 2024-11-04 16:23:07 -05:00
commit c3c690c3ed
No known key found for this signature in database
4 changed files with 534 additions and 0 deletions

6
CMakeLists.txt Normal file

@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.29)
project(cmpsc330hw3)
set(CMAKE_CXX_STANDARD 20)
add_executable(cmpsc330hw3 main.cxx exact_number.h exact_number.cxx)

109
exact_number.cxx Normal file

@ -0,0 +1,109 @@
#include "exact_number.h"
using namespace std;
ExactNumber::ExactNumber(){
numer = 0;
denom = 1;
}
ExactNumber::ExactNumber(int n, int d){
numer = n;
denom = d;
simplify();
}
ExactNumber::ExactNumber(const ExactNumber& n) {
numer = n.numer;
denom = n.denom;
}
ExactNumber::~ExactNumber() {
}
ExactNumber& ExactNumber::operator=(const ExactNumber& rhs) {
numer = rhs.numer;
denom = rhs.denom;
return *this;
}
ExactNumber& ExactNumber::operator+=(const ExactNumber& rhs) {
numer = numer * rhs.denom + denom * rhs.numer;
denom *= rhs.denom;
simplify();
return *this;
}
ExactNumber& ExactNumber::operator-=(const ExactNumber& rhs) {
numer = numer * rhs.denom - denom * rhs.numer;
denom *= rhs.denom;
simplify();
return *this;
}
ExactNumber& ExactNumber::operator*=(const ExactNumber& rhs) {
numer *= rhs.numer;
denom *= rhs.denom;
simplify();
return *this;
}
ExactNumber& ExactNumber::operator/=(const ExactNumber& rhs) {
numer *= rhs.denom;
denom *= rhs.numer;
simplify();
return *this;
}
ExactNumber operator+(const ExactNumber& lhs, const ExactNumber& rhs) {
ExactNumber result(lhs);
result += rhs;
return result;
}
ExactNumber operator-(const ExactNumber& lhs, const ExactNumber& rhs) {
ExactNumber result(lhs);
result -= rhs;
return result;
}
ExactNumber operator*(const ExactNumber& lhs, const ExactNumber& rhs) {
ExactNumber result(lhs);
result *= rhs;
return result;
}
ExactNumber operator/(const ExactNumber& lhs, const ExactNumber& rhs) {
ExactNumber result(lhs);
result /= rhs;
return result;
}
bool ExactNumber::operator==(const ExactNumber& rhs) const {
return numer == rhs.numer && denom == rhs.denom;
}
bool ExactNumber::operator!=(const ExactNumber& rhs) const {
return numer != rhs.numer || denom != rhs.denom;
}
bool ExactNumber::operator<(const ExactNumber& rhs) const {
return numer * rhs.denom < denom * rhs.numer;
}
bool ExactNumber::operator>(const ExactNumber& rhs) const {
return numer * rhs.denom > denom * rhs.numer;
}
bool ExactNumber::operator<=(const ExactNumber& rhs) const {
return numer * rhs.denom <= denom * rhs.numer;
}
bool ExactNumber::operator>=(const ExactNumber& rhs) const {
return numer * rhs.denom >= denom * rhs.numer;
}
ostream& operator<<(ostream& os, const ExactNumber& n) {
os << n.numer << "/" << n.denom;
return os;
}

106
exact_number.h Normal file

@ -0,0 +1,106 @@
/*************************************************************************
* CMPSC 330 *
* Startup code for HW 3 *
* Hyuntae Na, hzn17@psu.edu *
* *
* *
* Description: *
* *
* This is a header file for class ExactNumber. *
* Do not modify this file and implement each methods defined here in *
* exact_number.cxx *
* *
* Please report any bug to hzn17@psu.edu *
*************************************************************************/
#ifndef EXACTNUMBER_1_H
#define EXACTNUMBER_1_H
#include <iostream>
using namespace std;
class ExactNumber
{
private:
int numer;
int denom;
// private methods
// - implementations are provided in this file
inline int gcd() const;
inline void simplify();
public:
ExactNumber();
ExactNumber(int n, int d = 1);
ExactNumber(const ExactNumber& n);
~ExactNumber();
// implicit type conversion operator
// - implementation is provided in this file
inline operator double() const;
// assignment operator
ExactNumber& operator=(const ExactNumber& rhs);
// arithmatic operators
ExactNumber& operator+=(const ExactNumber& rhs);
ExactNumber& operator-=(const ExactNumber& rhs);
ExactNumber& operator*=(const ExactNumber& rhs);
ExactNumber& operator/=(const ExactNumber& rhs);
friend ExactNumber operator+(const ExactNumber& lhs, const ExactNumber& rhs);
friend ExactNumber operator-(const ExactNumber& lhs, const ExactNumber& rhs);
friend ExactNumber operator*(const ExactNumber& lhs, const ExactNumber& rhs);
friend ExactNumber operator/(const ExactNumber& lhs, const ExactNumber& rhs);
// equality/inequality operators
bool operator==(const ExactNumber& rhs) const;
bool operator!=(const ExactNumber& rhs) const;
// relational operators
bool operator< (const ExactNumber& rhs) const;
bool operator> (const ExactNumber& rhs) const;
bool operator<=(const ExactNumber& rhs) const;
bool operator>=(const ExactNumber& rhs) const;
// stream insertion/extraction operators as friend
friend ostream& operator<< (ostream& os, const ExactNumber& n);
};
// Implementation of private methods
// returns the greatest common divisor of number and denom
// - Eulclid algorithm for gcd
inline int ExactNumber::gcd() const
{
int n = (numer < 0) ? -numer : numer;
int d = (denom < 0) ? -denom : denom;
while (n > 0) {
int tmp = d % n;
d = n;
n = tmp;
}
return d;
}
// Simplifies the rational number
inline void ExactNumber::simplify()
{
int d = gcd();
numer /= d;
denom /= d;
}
// implicite type conversion operator to double
inline ExactNumber::operator double() const
{
return static_cast<double>(numer) / static_cast<float>(denom);
}
#endif

313
main.cxx Normal file

@ -0,0 +1,313 @@
#include <iostream>
#include <sstream>
#include <limits>
#include <cmath>
#include <string>
#include "exact_number.h"
using namespace std;
string error_msg(string rand, ExactNumber &n, double ans) {
ostringstream msg;
msg << " " << rand << " failed with " << static_cast<double>(n) << "... expecting " << ans;
return msg.str();
}
string error_msg(string rand, ExactNumber &n1, ExactNumber &n2, bool ans) {
ostringstream msg;
msg << " " << rand << " failed with " << ans << "... expecting " << !ans
<< " => " << n1 << " : " << n2 << endl;
return msg.str();
}
int main() {
cout << "Testing ExactNumber..." << endl << endl;
cout << "Manual check:";
cout << " operator<< should print an ExactNumber as \"(a/b)\"" << endl;
ExactNumber e1; // default constructor
cout << " manual check for (0/1) : " << e1 << endl;
ExactNumber e2(3); // memberwise-copy constructor
cout << " manual check for (3/1) : " << e2 << endl;
ExactNumber e3(5, 2); // memberwise-copy constructor
cout << " manual check for (5/2) : " << e3 << endl;
ExactNumber e4(e3); // copy constructor
cout << " manual check for (5/2) : " << e4 << endl;
ExactNumber e5(10, 5); // simplification
cout << " manual check for (2/1) : " << e5 << endl;
cout << endl;
cout << "Automatic check" << endl;
cout.precision(numeric_limits<double>::digits10);
unsigned int num_tests = 0;
unsigned int num_failed = 0;
ExactNumber n1(2, 4), n2(5, 3), n3(5, 6), n4;
// =
num_tests++;
n4 = n1;
try { if (static_cast<double>(n4) != 1.0 / 2.0) throw error_msg("operator=", n4, 1.0 / 2.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
// +=, -=, *=, /=
num_tests++;
n4 += n2;
try { if (static_cast<double>(n4) != 13.0 / 6.0) throw error_msg("opeator=", n4, 13.0 / 6.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 -= n2;
try { if (static_cast<double>(n4) != 1.0 / 2.0) throw error_msg("operator-=", n4, 1.0 / 2.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 *= n2;
try { if (static_cast<double>(n4) != 5.0 / 6.0) throw error_msg("operator*=", n4, 5.0 / 6.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 /= n2;
try { if (static_cast<double>(n4) != 1.0 / 2.0) throw error_msg("operator/=", n4, 1.0 / 2.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
// +, -, *, /
num_tests++;
n4 = n1 + n2;
try { if (static_cast<double>(n4) != 13.0 / 6.0) throw error_msg("operator+", n4, 13.0 / 6.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = n1 - n2;
try { if (static_cast<double>(n4) != -7.0 / 6.0) throw error_msg("operator-", n4, -7.0 / 6.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = n1 * n2;
try { if (static_cast<double>(n4) != 5.0 / 6.0) throw error_msg("operator*", n4, 5.0 / 6.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = n1 / n2;
try { if (static_cast<double>(n4) != 3.0 / 10.0) throw error_msg("operator/", n4, 3.0 / 10.0); }
catch (string m) {
cout << m << endl;
num_failed++;
}
// ==, !=
num_tests++;
n4 = n1 * n2;
bool result = n4 == n3;
try { if (result != true) throw error_msg("operator==", n4, n3, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n1 == n2;
try { if (result != false) throw error_msg("operator==", n4, n1, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n1 != n2;
try { if (result != true) throw error_msg("operator!=", n1, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n4 != n3;
try { if (result != false) throw error_msg("operator!=", n1, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
// <, >, <=, >=
num_tests++;
result = n1 < n2;
try { if (result != true) throw error_msg("operator<", n1, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n2 > n3;
try { if (result != true) throw error_msg("operator>", n2, n3, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n1 <= n2;
try { if (result != true) throw error_msg("operator<=", n1, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n2 <= n2;
try { if (result != true) throw error_msg("operator<=", n2, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n2 >= n3;
try { if (result != true) throw error_msg("operator>=", n2, n3, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
result = n2 >= n2;
try { if (result != true) throw error_msg("operator>=", n2, n2, result); }
catch (string m) {
cout << m << endl;
num_failed++;
}
// combination
num_tests++;
n4 = (n1 - n2) * n3 + n1;
try {
if (static_cast<double>(n4) != ExactNumber(-17, 36))
throw error_msg("(n1 - n2) * n3 + n1", n4, -17.0 / 36.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = n1 * n1 / n1 / n1;
try {
if (static_cast<double>(n4) != ExactNumber(1, 1))
throw error_msg("n1 * n1 / n1 / n1", n4, 1.0 / 1.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = n1 * n3 / n2 + n3 / n1 * n2;
try {
if (static_cast<double>(n4) != ExactNumber(109, 36))
throw error_msg("n1 * n3 / n2 + n3 / n1 * n2", n4, 109.0 / 36.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
num_tests++;
n4 = (n1 + n2) / (n3 * (n1 - n2) / (n3 + n1 * n2));
try {
if (static_cast<double>(n4) != ExactNumber(-26, 7))
throw error_msg("(n1 + n2) / (n3 * (n1 - n2) / (n3 + n1 * n2))", n4, -26.0 / 7.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
// operator* involving 0
ExactNumber n5(11, 3), n6(0, 5);
num_tests++;
n4 = n5 * n6;
try {
if (static_cast<double>(n4) != ExactNumber(0, 1))
throw error_msg("operator* involving 0", n4, 0.0 / 1.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
// operator/ involving 0
num_tests++;
n4 = n5 / n6;
try {
if (static_cast<double>(n4) != ExactNumber(1, 0))
throw error_msg("operator/ involving 0", n4, 0.0 / 1.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
/* Do not modify the code below */
// the famous FDIV bug
// https://en.wikipedia.org/wiki/Pentium_FDIV_bug
ExactNumber n7(4195835, 3145727);
num_tests++;
n4 = n7;
try {
if (static_cast<double>(n4) != (4195835.0 / 3145727.0))
throw error_msg("operator/=", n4, 4195835.0 / 3145727.0);
}
catch (string m) {
cout << m << endl;
num_failed++;
}
if (num_failed == 0) {
cout << "passed all " << num_tests << " default test cases" << endl;
} else {
cout << "failed " << num_failed << " default test cases out of " << num_tests << " default test cases" << endl;
}
cout << endl;
return 0;
}