1 / 25

Case Study - Fractions

Case Study - Fractions. Timothy Budd Oregon State University. Objectives. To easily create new instances of the rational number abstraction. To manipulate rational numbers using arithmetic operations, yielding new rational number results.

Download Presentation

Case Study - Fractions

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Case Study - Fractions Timothy Budd Oregon State University

  2. Objectives • To easily create new instances of the rational number abstraction. • To manipulate rational numbers using arithmetic operations, yielding new rational number results. • It should be possible to mix rationals and other arithmeticquantities in the same expression. • It should be possible to assign a rational number value to arational number variable. • The modification forms of assignment should be supported. • To compare one rational number to another. • It should be possible to perform input and output operations with rational numbers.

  3. Example of Rational Numbers // probability one is 1 in 8rational p1 (1,8); // probability two is 2 in 3rational p2 (2, 3); // probably of both together is their productrational p3 = p1 * p2; // probably of either independent is their sumrational p4 = p1 + p2; // what is this probability?cout << "combined probability is " << p3 << endl;cout << "independent probability is " << p4 << endl

  4. Definition of Operations on Rational Numbers

  5. // class rational// rational number data abstraction class rational {public: // constructors rational () : top(0), bottom(1) { } rational (int t) : top(t), bottom(1) { } rational (int t, int b) : top(t), bottom(b) { normalize(); } rational (const rational & r) : top(r.top), bottom(r.bottom) { } // accesser functions int numerator () const { return top; } int denominator () const { return bottom; } // assignments void operator = (const rational & r) {top = r.top; bottom = r.bottom;} void operator += (const rational &); // other operations operator double () const { return top / (double) bottom; } const rational & operator++() { top += bottom; return this; } const rational operator++(int);private: int top; // data areas int bottom; void normalize (); // operation used internally };

  6. Interface and Implementation • The code associated with a component is separated into two files. • The interface file describes how to use the component. • The implementation file contains the actual code to perform the actions. • The class description is divided into two parts. • Public: behaviors and data fields that users of the data abstraction can access. • Private: behavior and fields that are accessible only within the component and are off-limits to other users.

  7. Constructors • Every class should define a default constructor. • Use initializes whenever possible. • The declaration that uses an empty parentheses list is not syntactically incorrect; simply not doing what the programmer expects. • Every class should define a copy constructor.

  8. Member Function • Anaccessorfunction provides access to the internal state of an object. left.numerator() * right.denominator() + right.numerator() * left.denominator() • A function defined as part of the behavior of a class is called amember function. • Theconstkeyword in C++ is not the same as thefinalkeyword in Java.

  9. Operators • In C++, operators can potentially have overloaded meanings. • Requirement: the definition must not require arguments that match any existing definition. • Can be achieved if one or both arguments are a new data type, since no existing definition can be using these types.

  10. Operators const rational operator + (const rational & left, const rational & right) { // return sum of two rational numbers rational result ( left.numerator() * right.denominator() + right.numerator() * left.denominator(), left.denominator() * right.denominator()); return result; } • The address operator in the argument list indicates that the left and right values will be passedby reference.

  11. Operators • A list of prototypes for the arithmetic operations. // prototypes for arithmetic operations, including unary negationconst rational operator + (const rational &, const rational &);const rational operator - (const rational &, const rational &);const rational operator * (const rational &, const rational &);const rational operator / (const rational &, const rational &);const rational operator - (const rational &);bool operator < (const rational &, const rational &);bool operator == (const rational &, const rational &);

  12. Unary Negation Operator const rational operator - (const rational & val) { // return negation of argument value return rational (- val.numerator(), val.denominator()); }

  13. Comparison Operators bool operator < (const rational & left, const rational & right) { // less than comparison of two rational numbers return left.numerator() * right.denominator() < right.numerator() * left.denominator(); } bool operator == (const rational & left, const rational & right) { return left.numerator() * right.denominator() == right.numerator() * left.denominator(); }

  14. Increment and Decrement • The variablethisis a value in Java but is a pointer in C++. class rational { ... const rational & operator ++ () { top += bottom; return *this;} ... }; const rational rational::operator++ (int) { // increment fraction, but return original value, make clone rational clone(*this); top += bottom; // make change return clone; // return clone }

  15. Functions • Functions cannot access the internal (private) structure of any class, unless declared as afriend. const rational abs (const rational & num) { // return the absolute value of a rational number int newtop; int newbottom = num.denominator(); // get non-negative numerator part if (num.numerator() < 0) newtop = - num.numerator(); else newtop = num.numerator(); // create and return result return rational(newtop, newbottom);}

  16. Member Function Operators void rational::operator += (const rational & right) { // modify by adding right hand side top = top * right.denominator() + bottom * right.numerator(); bottom *= right.denominator(); // normalize the result, ensuring lowest denominator form normalize(); }

  17. void rational::normalize() { // normalize rational by (a) moving sign to numerator :// b) making sure numerator and denominator have no common divisorsint sign = 1; // sign is 1 if non-negative, -1 if negativeif (top < 0) { sign = -1; top = - top;}if (bottom < 0) { sign = - sign; bottom = - bottom;}// make sure we are not dividing by zeroif (bottom == 0)throw range_error("fraction with zero numerator");// find greatest common divisor int d = gcd(top, bottom);// move sign to top and divide by gcdtop = sign * (top / d);bottom = bottom / d; }

  18. Member Function Operators try { ... // computation involving rationals} catch (range_error & e) { printf("got exception %s", e.what()); }

  19. Conversion Operations • Constuctors are also used implicitly. rational x, y; ...x = y * 3; • Temporary values can also be created directly by the programmer, by invoking the constructor as if it were an ordinary function. x = y * rational(3, 4);

  20. Conversion Operations • Conversions the other direction, from an object type to another type, are defined using a conversion operator. • A conversion operator is an operator whose name is a type. class rational { ... operator double () const { return top / (double) bottom; }};

  21. Conversion Operations • Avoidcastif possible, but if unavoidable use astaticordynamiccast. rational x(3, 4);cout << "3/4 of pi is " << (3.14 * double(x)) << '\n';

  22. Input and Output Streams • Output is easily accommodated by redefining the left shift operator <<, and providing a new meaning. ostream & operator << (ostream & out, const rational & value) { // print representation of rational number on // an output stream out << value.numerator() << '/' << value.denominator(); return out; }

  23. Input and Output Streams • Predefined precedence is low enough to allow arithmetic expressions to appear in output without using parenthesis, as in: cout << "a + b * c is " << a + b * c << '\n'; • The left shift operator with its conventional meaning can be used in anoutput statement, by surrounding it with parenthesis: cout << " a left shift by 3 is " << (a << 3) << '\n';

  24. Stream Input • A loop that would read values repeatedlyfrom the input until end of file could be written as: while (cin >> intval) { // process intval ...}// reach this point on end of input... • An easy way to remember, the stream I/O operations is to visualize them as arrows. • The input operator, >> x, points data into x, whilethe output operator, << x, copies data out of x.

  25. istream & operator >> (istream & in, rational & r) { // read a rational number from an input streamint t, b;// read the topin >> t;// if there is a slash, read the next numberchar c;in >> c;if (c == '/') in >> b; // read bottom partelse { in.putback(c); b = 1;}// do the assignmentrational newValue(t, b);r = newValue;// return the streamreturn in; }

More Related