Project 3: Fractions

CSE 143
Summer 1998

For this assignment, you will implement a Fraction class and a client using that class. A Fraction represents the ratio of an int and a non-zero int. Fractions will support the following operations: addition, subtraction, multiplication, division, negation, test for equality, printing to an ostream, conversion to a C++ double, and arbitrary-precision decimal expansion. In addition to representing rational values, the Fraction class must also represent the exceptional values Inf (infinity), -Inf (negative infinity), and NaN (not a number). The client is a simple calculator that keeps its results as a fraction rather than as a floating point number.

Operations on fractions

The following table shows how to handle exceptional cases that will result in Inf, -Inf, or NaN.
Op1 Op2 + - * /
NaN * NaN NaN NaN NaN
* NaN NaN NaN NaN NaN
Inf Inf Inf NaN Inf NaN
Inf -Inf NaN Inf -Inf NaN
Inf i Inf Inf Inf Inf
Inf -i Inf Inf -Inf -Inf
Inf 0 Inf Inf NaN Inf
-Inf Inf NaN -Inf -Inf NaN
-Inf -Inf -Inf NaN Inf NaN
-Inf i -Inf -Inf -Inf -Inf
-Inf -i -Inf -Inf Inf Inf
-Inf 0 -Inf -Inf NaN -Inf
i Inf Inf -Inf Inf 0
i -Inf -Inf Inf -Inf 0
i 0 i i 0 Inf
-i Inf Inf -Inf -Inf 0
-i -Inf -Inf Inf Inf 0
-i 0 -i -i 0 -Inf
0 Inf Inf -Inf NaN 0
0 -Inf -Inf Inf NaN 0
0 0 0 0 0 NaN

In the above table, '*' as an Op value means any value, 'i' represents any positive, non-exceptional value, and -i represents any negative, non-exceptional value.

Overflow: Because the Fraction class represents the ratio of 2 C++ ints, it is possible to manipulate Fractions in such a way as to produce a value which cannot be represented by two C++ ints. More disturbingly, badly-organized code may result in an overflow during an intermediate step even though the final result could be represented as the ratio of two ints. Ideally, you would like to structure your code to eliminate or at least reduce occurences of integer overflow. The following is a list, from simplest (least robust) to most complex (most robust), of ways to deal with this problem.

A caveat: it is possible to have a Fraction such that overflow occurs in the call to expand. This happens in the sample executable we have provided, and it is acceptable to do what we do (have expand return false if overflow occurs in the expansion process). However, it is possible to correctly expand these Fractions to the specified precision using a more complicated method of long division; you will receive extra credit if you do this, but you should do so only after the rest of your code is correctly completed (see our suggested approach below)

Moving down this list by writing more elaborate checks will earn you more credit; however, this assignment is not about solving the problem of overflow. Simply stopping after the first step ("ignore the problem") will earn you almost full credit. Please do not attempt to solve the more complex problems related to overflow until you have finished the rest of the assignment. See the "Suggested Approach" section of the homework for more information.

Note that to handle overflow, you'll find the header file limits.h very useful. It defines two extremely important constants: INT_MAX, the largest possible value an int can have, and INT_MIN, the smallest value an int can have. limits.h is defined in the C++ standard library, just like iostream.h.

The client

The client for the Fraction class is a simple calculator that operates on rational numbers. When run, the calculator displays the current value it is computing (which defaults to NaN). The user can enter any of the following commands, followed by the Enter key.

<number>
Set the current value to be <number>.
-
Negate the current value.
d
Display the current value as represented by a C++ double.
e
Display the current value as a decimal value expanded to a string of length 80 (be careful to maintain your discipline and avoid "magic numbers" in your code).
<op> <number>
Set value to (value <op> <number>). The whitespace between <op> and <number> is optional.

In the above list, <number> is either a string of digits, or a fraction composed of a string of digits followed by the character '/' followed by another string of digits. Hence, "1" and "1/2" are valid numbers, but "1/" is not. You don't need to worry about what happens if either string of digits is too big to fit in an int until you get to handling overflow. Notice that number cannot be negative; this is for simplicity. If you want to subtract -3, you have to add 3. If you want to divide by -3, you have to divide by 3 and negate the result separately.

Any line that does not fit one of the above descriptions should give the message "incomprehensible line ignored", and should not change the current value.

After each command is interpreted, the new value (which might be the same as the old value, e.g. when the line is not understood) should be displayed, and then the client waits for another command.

Also, <op> represents one of '+', '-', '*', and '/'.

Detailed Specification

Program organization: Your project will consist of 5 or 7 files.

Two files are supplied in their final form, and cannot be changed:

Two files have been given and should be modified as specified:

The following file is not supplied and should be written by you:

The following files are optional, and relate to the correct handling of arithmetic overflow in your Fraction implementation. If you choose to handle overflow, put any functions you create related to this task in these two files.

Suggested Approach

We suggest you approach this assignment by breaking it down into the following pieces:

  1. Implement the Fraction class in a straightforward manner. Do not worry about the exceptional cases, or about what happens if two Fractions can each be represented as the ratio of two C++ ints, but their product/sum/whatever cannot. Do not implement Fraction::expand at this time. Test your implementation by writing a simple driver that creates a few Fractions, performs operations on them, and prints out the results. Use our sample executable to compare your answers with ours.
  2. Add in handling of exceptional cases (Inf, -Inf, NaN, dividing by zero, etc.). Test the special cases to verify that your answers match those in the table above.
  3. Implement the client. Compare your client with the sample executable we have given you.
  4. Implement the expand function, replacing our dummy implementation.
  5. Handle overflow in the arithmetic operations.
  6. Eliminate overflow in the expand function (this should be absolutely positively the last thing you implement, and is for extra credit only!)

Executable

To verify that your solution is working correctly, we encourage you to compare it against our sample solutions. The following links will allow to download sample Windows and x86 Linux executables.

Turn-In

Homework 3 is due on Monday, July 20th, 1998, at 5:00pm. You will turn in your homework using a form on the course web, and you will be unable to submit your homework after 5:00pm. Please plan your time so that you will not be trying to submit your assignment at 4:59.

When you're finished writing your solution, you can use the electronic turn-in form to submit it. Follow the instructions on that form (especially with regards to file naming conventions), print the receipt, and submit the receipt at the start of section, Tuesday, July 21st, 1998. For full credit, you must turn in electronically, print the receipt, and hand in that receipt in your section. You may also be able to drop your receipt in the drop box located on the first floor of Sieg hall, across from room 127. More details on this will follow.

If You Get Stuck

If you're having problems, there are a number of resources available for you.

If you're struggling because you're having trouble expressing things in C++, you may want to try out some of the useful tips I provided. Although you don't need any of these to do well on the assignment, they are ideas that can simplify a lot of potentially ugly code.

If you need help with the lab environment or the online resources, go talk to a consultant in the IPL.

If you can't make progress in the actual assignment, please talk to the instructor or a TA. They are available during posted office hours, and sometimes by appointment. They will also occasionally help you out over email. You are invited to seek help from any available TA, not just your own.

You can discuss the assignment in general terms with other students. You can ask general questions on the student discussion list for this course, cse143@cs. But any code you write must be your own. For more details about what is and is not allowed, see the Software hygiene page.


cse143-webmaster@cs.washington.edu