230 likes | 377 Views
CSE 20232 Lecture 22 – Class Example. Rational Number Class (p/q), where p & q are integers and q > 0 Members numer & denom Public Functions Constructors Operators: + - * / I/O: >> << Private Functions reduce() & gcd() Makes sign part of numer & removes all common factors.
E N D
CSE 20232Lecture 22 – Class Example • Rational Number Class • (p/q), where p & q are integers and q > 0 • Members • numer & denom • Public Functions • Constructors • Operators: + - * / • I/O: >> << • Private Functions • reduce() & gcd() • Makes sign part of numer & removes all common factors
Reading, Etc. • Weekly Reading: • Sections: • 10.1-10.5, 10.7-10.8 • 11.1-11.12 • Later this week & next • Big Clock Class • Complex Numbers • Mandelbrot and Julia Sets • TEST # 2 – next Wednesday
Macro guards • This is a quick aside • Protect your headers from being compiled more than once in the same scope • Otherwise, you may get “multiple declaration of … in the same scope” errors from the compiler • The following is a macro guard using #define for the header file “rational.h” #ifndef JHS_RATIONAL_H // JHS_RATIONAL_H is NOT defined, so define it and continue #define JHS_RATIONAL_H // all code (class definitions, prototypes, etc) goes here #endif
How the macro guard works • The first time the preprocessor “includes” the header, the constant is NOT defined, so it gets defined, and the header code is processed by the compiler • The second time the preprocessor “includes” the header, during the same compilation, the constant IS defined already, so the code between “#ifndef …” and “#endif” is skipped
Header “rational.h” // rational.h - JHS - 2006 #ifndef JHS_RATIONAL_H #define JHS_RATIONAL_H #include <iostream> // do NOT put “using namespace std;” here - considered poor form class Rational { public: Rational(void); Rational(const Rational& x); Rational(int n, int d); void setNumerator(int n); void setDenominator(int d); int getNumerator(void) const; int getDenominator(void) const;
Header “rational.h” // overloaded >> and << operators for I/O, note use of “std::” friend std::ostream& operator<<(std::ostream& out, Rational r); friend std::istream& operator>>(std::istream& in, Rational& r); // overloaded mathematics operators Rational operator+(Rational x); // (*this) + x Rational operator-(Rational x); // (*this) - x Rational operator*(Rational x); // (*this) * x Rational operator/(Rational x); // (*this) / x Rational operator+(int n); // (*this) + n Rational operator-(int n); // (*this) - n Rational operator*(int n); // (*this) * n Rational operator/(int n); // (*this) / n
Header “rational.h” private: int denom, numer; // private utility functions (greatest common divisor & reduce) int gcd (int a, int b); void reduce(void); }; // end of Rational class // non member utility functions for computing (int op Rational) Rational operator+(int n, Rational x); // n + x Rational operator-(int n, Rational x); // n - x Rational operator*(int n, Rational x); // n * x Rational operator/(int n, Rational x); // n / x #endif // JHS_RATIONAL_H
Rational Operations • Sum • a/b + c/d = (a*d + c*b) / (b*d) • Difference • a/b – c/d = (a*d – c*b) / (b*d) • Product • a/b * c/d = (a*c) / (b*d) • Quotient • (a/b) / (c/d) = (a/b) * (d/c) = (a*d) / (b*c)
Rational Operations • Reducing fractions • Find greatest common divisor of a/b • g = gcd(a,b) • Scale numerator and denominator • Reduced result = (a/g) / (b/g)
Rational Operations • Greatest Common Divisor (Euclid’s Method) • Given a/b • if (d == 0) then gcd(a,b) = a • else gcd(a,b) = gcd(b, a%b) • Example 45 / 105 = (3*3*5) / (3*5*7) • 45 / 105 0 with remainder 45 • 105 / 45 3 with remainder 15 • 45 / 15 3 with remainder 0 • 15 / 0 so gcd(45,105) = 15 • and 45 / 105 is 3 / 7 in reduced form
Source Code “rational.cpp” // rational2.cpp -JHS - 2006 #include "rational2.h“ // which includes <iostream> // the constructors Rational::Rational( ) // default (0/1) : numer(0), denom(1) { } Rational::Rational(const Rational& x) // copy constructor, copies x : numer(x.numer), denom(x.denom) { } Rational::Rational(int n, int d) // creates (n/d), in reduced form : numer(n), denom(d) { reduce(); }
Source Code “rational.cpp” // functions for accessing and modifying object state void Rational::setNumerator(int n) { numer = n; reduce(); } void Rational::setDenominator(int d) { denom = d; reduce(); } int Rational::getNumerator(void) const { return numer; } int Rational::getDenominator(void) const { return denom; }
Source Code “rational.cpp” // friend functions for I/O operations >> and << std::ostream& operator<<(std::ostream& out, Rational r) { out << r.numer << '/' << r.denom; // output with / separator return out; // required for use like this: cout << x << y; } std::istream& operator>>(std::istream& in, Rational& r) { char str[80]; in.getline(str,32,'/'); // get numerator as string r.numer = atoi(str); // convert it to number in >> r.denom; // get denominator r.reduce(); // put number into reduced form return in; // required for use like this: cin >> x >> y; }
Source Code “rational.cpp” // addition operators Rational Rational::operator+(Rational x) { Rational s; s.numer = numer * x.denom + x.numer * denom; s.denom = denom * x.denom; s.reduce(); return s; } Rational Rational::operator+(int n) { return (*this + Rational(n,1)); } Rational operator+(int n, Rational x) // non member { return (Rational(n,1) + x); }
Source Code “rational.cpp” // subtraction operators Rational Rational::operator-(Rational x) { Rational d; d.numer = numer * x.denom - x.numer * denom; d.denom = denom * x.denom; d.reduce(); return d; } Rational Rational::operator-(int n) { return (*this - Rational(n,1)); } Rational operator-(int n, Rational x) // non member { return (Rational(n,1) - x); }
Source Code “rational.cpp” // multiplication operators Rational Rational::operator*(Rational x) { Rational p; p.numer = numer * x.numer; p.denom = denom * x.denom; p.reduce(); return p; } Rational Rational::operator*(int n) { return (*this * Rational(n,1)); } Rational operator*(int n, Rational x) // non member { return (Rational(n,1) * x); }
Source Code “rational.cpp” // division operators Rational Rational::operator/(Rational x) { Rational q; q.numer = numer * x.denom; q.denom = denom * x.numer; q.reduce(); return q; } Rational Rational::operator/(int n) { return (*this / Rational(n,1)); } Rational operator/(int n, Rational x) // non member { return (Rational(n,1) / x); }
Source Code “rational.cpp” // private utility functions // find greatest common divisor of a & b, using Euclid’s Method // gcd(a,b) = a if b = 0, // gcd(a,b) = gcd(b,a%b), otherwise int Rational::gcd(int a, int b) { int q = abs(a); int r = abs(b); while (q % r > 0) // if r is a factor of q, r is the answer { int newr = q % r; // otherwise, find remainder q = r; // and set up to divide value of r r = newr; // by the remainder of the division } return r; }
Source Code “rational.cpp” // reduce number by removing all common divisors from // numer & denom void Rational::reduce(void) { if (denom == 0) { std::cout << “ERROR: Zero denominator in “ << *this << ‘\n’; exit(1); // divide by zero is not allowed } if (denom < 0) { denom = -denom; // make sure the sign is associated numer = -numer; // with the numerator } int factor = gcd(numer,denom); // find greatest common divisor numer = numer / factor; // remove it from numerator denom = denom / factor; // remove it from denominator }
Source Code “rtester.cpp” // rtester.cpp - JHS - 2006 // test program for Rational class #include "rational.h" using namespace std; int main (void) { Rational x,w; // default constructor test Rational y(3,5); // set y to 3/5 Rational z(y); // copy constructor test int n; cout << "Enter a rational number (ex: 3/4) and an integer\n"; cin >> x >> n; cout << "x = " << x << '\n'; cout << "y = " << y << '\n'; cout << "z = " << z << '\n'; cout << “n = " << n << '\n';
Source Code “rtester.cpp” // test addition & subtraction w = x + z; cout << "Sum x + z = " << w << '\n'; w = x + n; cout << "Sum x + n = " << w << '\n'; w = n + z; cout << "Sum n + z = " << w << '\n'; w = x - z; cout << "Diff x - z = " << w << '\n'; w = x - n; cout << "Diff x - n = " << w << '\n'; w = n - z; cout << "Diff n - z = " << w << '\n';
Source Code “rtester.cpp” // test multiplication & division w = x * z; cout << "Prod x * z = " << w << '\n'; w = x * n; cout << "Prod x * n = " << w << '\n'; w = n * z; cout << "Prod n * z = " << w << '\n'; w = x / z; cout << "Quot x - z = " << w << '\n'; w = x / n; cout << "Quot x - n = " << w << '\n'; w = n / z; cout << "Quot n - z = " << w << '\n'; return 0; }