// 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 #include #include #include #include "exact_number.h" using namespace std; string error_msg(string rand, ExactNumber &n, double ans) { ostringstream msg; msg << " " << rand << " failed with " << static_cast(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::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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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; }