#include using namespace std; namespace NumberAlgorithms { template T Max(const T& a, const T& b) { return (a > b) ? a : b; } template T Min(const T& a, const T& b) { return (a < b) ? a : b; } template T GreatestCommonFactor(const T& a, const T& b) { T gcf = 1, max = Min(a, b); for (T i = 2; i < max; i++) if (a % i + b % i == 0) gcf = i; return gcf; } template T LeastCommonMultiple(const T& a, const T& b) { T max = a * b; for (T i = Min(a, b); i < max; i++;) if (i % a + i % b == 0) return i; } }; // Fraction SHOULD be a struct, as it is a data type, and doesn't function // with other objects. Other objects use it, but it doesn't depend on anything. // T must be an number type (representing any real rational number) template // It is not possible to use constraints in c++ class Fraction // So we have to assume that the user will use an integral type { private: T Numerator, Denominator; void Reduce() { T gcf = NumberAlgorithms::GreatestCommonFactor(Numerator, Denominator); Numerator /= gcf; Denominator /= gcf; if (Denominator < 0) { Numerator *= -1; Denominator *= -1; } } public: Fraction() : Numerator(1), Denominator(1) { } Fraction(T n) : Numerator(n) { SetDenominator(1); } Fraction(T n, T d) : Numerator(n) { SetDenominator(d); } void SetNumerator(const T& value) { Numerator = value; Reduce(); } T GetNumerator() const { return Numerator; } void SetDenominator(const T& value) { if (value == 0) throw std::exception("Divide by zero"); Denominator = value; Reduce(); } T GetDenominator() const { return Denominator; } friend ostream& operator<<(const ostream& output, const Fraction value); friend istream& operator>>(const istream& input, Fraction value); friend Fraction operator+(const Fraction& left, const Fraction& right); friend Fraction operator-(const Fraction& left, const Fraction& right); friend Fraction operator*(const Fraction& left, const Fraction& right); friend Fraction operator/(const Fraction& left, const Fraction& right); bool operator<(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d < b * c); } bool operator>(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d > b * c); } bool operator<=(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d <= b * c); } bool operator>=(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d >= b * c); } bool operator==(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d == b * c); } bool operator!=(const Fraction& right) const { T a = GetNumerator(), b = GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); return (a * d != b * c); } }; template Fraction operator+(Fraction const& left, Fraction const& right) { T a = left.GetNumerator(), b = left.GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(), x; using NumberAlgorithms; x = LeastCommonMultiple(b, d); a *= x / d; b *= x / d; c *= x / b; d *= x / b; return Fraction(a + b, c); } template Fraction operator-(Fraction const& left, Fraction const& right) { T a = left.GetNumerator(), b = left.GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(), x; using NumberAlgorithms; x = LeastCommonMultiple(b, d); a *= x / d; b *= x / d; c *= x / b; d *= x / b; return Fraction(a - b, c); } template Fraction operator*(Fraction const& left, Fraction const& right) { T a = left.GetNumerator(), b = left.GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); if (b == 0 || d == 0) throw exception("Divide by zero"); return Fraction(a * c, b * d); } template Fraction operator/(Fraction const& left, Fraction const& right) { T a = left.GetNumerator(), b = left.GetDenominator(), c = right.GetNumerator(), d = right.GetDenominator(); if (c == 0 || d == 0) throw new exception("Divide by zero"); return Fraction(a * d, b * c); } template ostream& operator<<(const ostream& output, const Fraction& value) { output << value.Numerator << '/' << value.Denominator; return output; } template istream& operator>>(const istream& input, Fraction& value) { T n, d, char seperator; cin >> n >> seperator >> d; value.SetNumerator(n); value.SetDenominator(d); return input; } bool Test() { char answer; Fraction test1, test2, test3(10); int a, b; cout << endl << "Please enter two whole numbers. ex: a b : "; cin >> a >> b; test1 = Fraction(a, b); cout << endl << "Please enter two whole numbers. ex: a/b : "; cin >> test2; // Display the three values to test cout cout << "\nTest1 equals " << test1; cout << "\nTest2 equals " << test2; cout << "\nTest3 equals " << test3; // Test our operators cout << "\nTest1 * Test2 equals " << test1*test2; cout << "\nTest1 / Test3 equals " << test1/test3; cout << "\nTest2 + Test3 equals " << test2+test3; cout << "\nTest3 - Test1 equals " << test3-test1; if (test1 == test2) cout << "\nTest1 is equal to Test2"; if (test1 < test2) cout << "\nTest1 is less than Test2"; cout << "Would you like to test again? "; cin >> answer; return answer == 'Y' || answer == 'y'; } int main() { cout << endl << "Project 11-5" << endl << endl << "Testing the Fraction class." << endl << "The fraction class stores a numerator and denominator digit (n/d)" << endl << "Let the testing commence!" << endl; while (Test()) ; }