527 lines
15 KiB
C++
527 lines
15 KiB
C++
// Name: Sandipsinh Rathod
|
|
// Email: sdr5549@psu.edu
|
|
// Class: CMPSC 330
|
|
// Program Exact Number
|
|
// Current Date: 4/11/24 4:25 PM
|
|
// Due Date: 5/11/24
|
|
//
|
|
// Description:
|
|
// Implementation for +, -, *, /, =, +=, -=, *=, /=, ==, !=, <, >, <=, >= etc.
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <limits>
|
|
#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++;
|
|
try {
|
|
n4 = n5 / n6;
|
|
if (static_cast<double>(n4) != ExactNumber(1, 0))
|
|
throw error_msg("operator/ involving 0", n4, 0.0 / 1.0);
|
|
}
|
|
catch (const exception& m) {
|
|
cout << m.what() << endl;
|
|
}
|
|
|
|
/* Do not modify the code below */
|
|
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;
|
|
|
|
num_tests = 0;
|
|
ExactNumber one(1, 1), two(2, 1), negative_one_point_five(-3, 2), zero(0, 1), three_point_five(7, 2), one_again(2,
|
|
2), fdiv_test_case(
|
|
4195835, 3145727);
|
|
|
|
// 1. FDIV bug check
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(fdiv_test_case) != (4195835.0 / 3145727.0))
|
|
throw runtime_error("FDIV bug check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 2. Test: Equal
|
|
num_tests++;
|
|
try {
|
|
if (!(one == one_again))
|
|
throw runtime_error("Equality check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 3. Test: Not Equal
|
|
num_tests++;
|
|
try {
|
|
if (one != one)
|
|
throw runtime_error("Inequality check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 4. Test: Greater Than
|
|
num_tests++;
|
|
try {
|
|
if (!(two > one))
|
|
throw runtime_error("Greater than check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 5. Test: Less Than
|
|
num_tests++;
|
|
try {
|
|
if (!(negative_one_point_five < one))
|
|
throw runtime_error("Less than check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 6. Test: Greater Than or Equal
|
|
num_tests++;
|
|
try {
|
|
if (!(two >= one))
|
|
throw runtime_error("Greater than or equal check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 7. Test: Less Than or Equal
|
|
num_tests++;
|
|
try {
|
|
if (!(negative_one_point_five <= one))
|
|
throw runtime_error("Less than or equal check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 8. Test: Addition
|
|
ExactNumber sum = one + two;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(sum) != 3.0)
|
|
throw runtime_error("Addition check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 9. Test: Subtraction
|
|
ExactNumber difference = two - one;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(difference) != 1.0)
|
|
throw runtime_error("Subtraction check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 10. Test: Multiplication
|
|
ExactNumber product = two * negative_one_point_five;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(product) != -3.0)
|
|
throw runtime_error("Multiplication check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 11. Test: Division
|
|
ExactNumber quotient = two / one;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(quotient) != 2.0)
|
|
throw runtime_error("Division check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 12. Edge Case: Division by Zero
|
|
num_tests++;
|
|
try {
|
|
ExactNumber div_by_zero_result = one / zero;
|
|
throw runtime_error("Division by zero check failed (expected exception).");
|
|
} catch (const exception &e) {
|
|
cout << "Caught division by zero as expected (skipping)" << endl;
|
|
}
|
|
|
|
// 13. Addition with Negative
|
|
ExactNumber addition_with_negative = negative_one_point_five + one;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(addition_with_negative) != -0.5)
|
|
throw runtime_error("Addition with negative check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 14. Subtraction with Negative
|
|
ExactNumber subtraction_with_negative = one - negative_one_point_five;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(subtraction_with_negative) != 2.5)
|
|
throw runtime_error("Subtraction with negative check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 15. Negative Multiplication
|
|
ExactNumber negative_product = negative_one_point_five * negative_one_point_five;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(negative_product) != 2.25)
|
|
throw runtime_error("Negative multiplication check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 16. Negative Division
|
|
ExactNumber negative_division = negative_one_point_five / two;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(negative_division) != -0.75)
|
|
throw runtime_error("Negative division check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 17. Multiplication by Zero
|
|
ExactNumber multiplication_by_zero = zero * two;
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(multiplication_by_zero) != 0.0)
|
|
throw runtime_error("Multiplication by zero check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 18. Self Assignment
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(one) != 1.0)
|
|
throw runtime_error("Self-assignment check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 19. Negative Self Multiplication
|
|
ExactNumber negative_self_multiplication = negative_one_point_five * ExactNumber(-1, 1);
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(negative_self_multiplication) != 1.5)
|
|
throw runtime_error("Negative self-multiplication check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
// 20. Fraction Reduction Check
|
|
ExactNumber fraction_reduction(10, 20);
|
|
num_tests++;
|
|
try {
|
|
if (static_cast<double>(fraction_reduction) != 0.5)
|
|
throw runtime_error("Fraction reduction check failed.");
|
|
} catch (const exception &e) {
|
|
cout << e.what() << endl;
|
|
num_failed++;
|
|
}
|
|
|
|
if (!num_failed) {
|
|
cout << "passed all " << num_tests << " custom test cases" << endl;
|
|
} else {
|
|
cout << "failed " << num_failed << " custom test cases out of " << num_tests << " custom test cases" << endl;
|
|
}
|
|
cout << endl;
|
|
|
|
return 0;
|
|
}
|