CIT 591 Assignment 5: Fraction Calculator
Fall 2011, David Matuszek

Purposes of this assignment

• To get you started with classes and objects.

General idea of the assignment

1. Finish and improve the `FractionTest` and `Fraction` classes that I developed during Wednesday's lecture.
2. Write a simple text-only (no GUI) calculator to compute with fractions.

Details

1. The Fraction API

Use Test Driven Design.

I wrote a `multiply` method. Write similar methods for `add`, `subtract`, and `divide`. Also write a method `absValue` to return the absolute value of a fraction, and `negate` to change the sign of a fraction. All of these methods should return a newly created Fraction, not change any existing Fraction.

Improve the `__str__` method so that, when given a Fraction whose denominator is `1`, just returns the numerator (as a string).

2. The text interface

Since we didn't do any of this in class, it will take longer to describe.

Write separate modules (files) named `FractionCalculatorTest` and `FractionCalculator`. The code described in this section goes in these modules, not in `Fraction` or `FractionTest`.

When the program first starts, the value in the calculator should be zero.

Accept lines of input from the user. Each line will contain some mixture of numbers and operators, separated by spaces (You can use `split()` to turn this string into a list.) For example,

`    3/4 + 1/-3 * 7 / 5`

Here's what to do for each input item:

When you see Do this
`+` Remember (in some variable) that you need to do an addition. For each of these, if there is already an operation being remembered, raise a `ValueError`.
`-` Remember (in some variable) that you need to do a subtraction.
`*` Remember (in some variable) that you need to do a multiplication.
`/` Remember (in some variable) that you need to do a division. (You can tell a division operator from part of a fraction because the` / `is all by itself.)
`a` or `A` or `abs` or... (An` a `or` A `or any word beginning with these) Take the absolute value of the fraction currently held by the calculator.
`n` or `N` or `neg` or... (An` n `or` N `or any word beginning with these) Change the sign of the fraction currently held by the calculator.
`c` or `C` or `clear` or... (A` c `or` A `or any word beginning with these) Set the value held by the calculator to zero.
A fraction

If you have a remembered operation (`+`,` -`,` *`, or` /`), perform the operation, with the value currently in the calculator as the first operand, and the fraction as the second operand. The result becomes the new value in the calculator. "Forget" the operation, since you have now used it.

If you do not have a remembered operation, then set the value in the calculator to the new fraction.

A whole number Treat this as a Fraction whose denominator is` 1`.
`q` or `Q` or `quit` or... (A` q `or `Q `or any word beginning with these) Raise an `EOFError`.
Anything else Stop processing any remaining input, set the value in the calculator to zero, and raise a `ValueError`.

Extended example: Some changes have been made after I realized that there was no good way to "remember" an operation across lines.

 After this input: Value in calculator is Remembered operation is `1/2` `-` `3/4` `*` `abs` `\n` `8` `7/8` `neg` `+` `0/1` `1/2` `1/2` `-1/4` `-1/4` `1/4` `1/4` `2/1 8 ` `7/8` `-7/8` `-7/8` `None` `None` `-` `None` `*` `*` `* None ` `None` `None` `None` `+`

In `FractionCalculator`, write a function `evaluate(fraction, inputString)`. The arguments are a Fraction to use as a starting value, and a string such as the user might type in. The result should be a new Fraction that is the result of doing the arithmetic, or the function might raise an exception that the calling method must catch. This function should do no input or output and must be unit tested.

The recommended way of doing the unit testing is:

1. Write a test for the feature you are about to add (such as addition, or entering a new fraction, or raising a `ZeroDivideException ZeroDivisionError`).
2. Test. This is just to make certain that the new feature fails, and to some extent is "testing the test."
3. Add to the `evaluate` method the code needed to handle the new feature.
4. Test. If the test fails, go back and fix either the code or the test until all the tests pass.
5. If you can see any way to improve the code without changing what it does (this is called "refactoring"), do it now, and test to make sure you haven't broken anything.
6. Repeat for the next feature.

Now, write a `main()` function to:

1. Initially set the value in the calculator to zero, with no "remembered" operation.
2. Print some kind of welcome message. It should include your name and the name of your partner.
3. Read lines of input from the user and, for each line, print just the final result of doing that line. Leave this final result as the current value in the calculator, so that the user can continue on the next line. Or, if any kind of exception occurs, other than `EOFError`, print the word `Error`, reset the calculator to its initial state, and discard the remainder of the input line, if any. For an `EOFError`, however, just print the word "`Goodbye`" and exit the program.

Submit your program, as a single `.zip` file, to Sakai, by 6am next Friday.