CIT 591 Assignment 9: Negadecimal Calculator
Fall 2014, David Matuszek

# Purposes of this assignment

• To get you started programming in Java.
• To introduce the use of more than one class.
• To learn some string manipulation.
• To familiarize you with JUnit testing in Java.

Note: This is probably the most abstract (and least practical) assignment you will get this semester.

# General idea of the assignment

Your assignment is to write a "calculator" for negadecimal integers. It will be able to do addition, subtraction, multiplication, and integer division, as well as negation and modulus (remainder). It will also have a one-number "display,", and it will be able to convert between decimal and negadecimal.

Negadecimal is a place notation like decimal, only instead of powers of 10, the notation uses powers of -10: 1, -10, 100, -1000, 10000, -100000, etc. For example,

 The number: In decimal, means: In negadecimal, means: 7 1 0 2 5 7*10000 1*1000 0*100 2*10 5*1 7*10000 1*-1000 0*100 2*-10 5*1

So, while 71025 is our usual decimal notation for 7102510 , the negadecimal number 71025-10 , translated to decimal, would be 68985.

An interesting characteristic of negadecimal is that numbers with an even number of digits are negative, while numbers with an odd number of digits are nonnegative (zero or positive).

It is easy to translate from negadecimal to decimal:

 5 times 1 is 5 2 times -10 is -20 0 times 100 is 0 1 times -1000 is -1000 7 times 10000 is 70000 5 - 20 + 0 - 1000 + 70000 = 68985

However, converting to negadecimal is more complicated. Fortunately, the Wikipedia article linked to above gives a C++ method for converting to negaternary, and this method can be easily adapted to one that converts to negadecimal. (Important: Don't try to use the Python version; the `%` operator gives different results for negative numbers.)

The user will use your program by typing in negadecimal expressions that modify the display. For example, if the display holds` 500` and the user types in `+692` , the calculator will compute `500+692` and display as` 19192 `as a result. Details of what the user may type are given below.

You should do unit testing of all your methods that don't do I/O, and we will also unit test your program. As you know, that means that our tests must be able to call your methods, so you should be extremely careful to write functions exactly as specified below.

# Classes

Each instance (object) of this class will represent one negadecimal number. That negadecimal number will be retained in an instance variable of type `int`.

The `NegadecimalNumber` class will have two constructors:

`public NegadecimalNumber(String s)`
This constructor expects a string representation of a negadecimal number, which it converts to a (decimal) `int` and stores in an instance variable. However, if the string does not consist entirely of digits, or is an empty string, an `IllegalArgumentException` should be thrown.
`public NegadecimalNumber(int n)`
Saves the integer (decimal) parameter in an instance variable.

In addition, the `NegadecimalNumber` class has a number of methods for maniuplating negadecimal numbers, and for combining them with other negadecimal numbers:

`public NegadecimalNumber add(NegadecimalNumber ndn)`
Returns a new negadecimal number which is the result of adding `ndn` to "this" negadecimal number.
`public NegadecimalNumber subtract(NegadecimalNumber ndn)`
Returns a new negadecimal number which is the result of subtracting `ndn` from "this" negadecimal number.
`public NegadecimalNumber multiply(NegadecimalNumber ndn)`
Returns a new negadecimal number which is the result of multiplying `ndn` and "this" negadecimal number.
`public NegadecimalNumber divide(NegadecimalNumber ndn)`
Returns a new negadecimal number which is the result of dividing "this" negadecimal number by `ndn`. Throws an `ArithmeticException` if `ndn` is zero.
`public NegadecimalNumber remainder(NegadecimalNumber ndn)`
Returns a new negadecimal number which is the remainder after dividing "this" negadecimal number by `ndn`. Throws an `ArithmeticException` if `ndn` is zero.
`public NegadecimalNumber negate()`
Returns a new negadecimal number which which, when added to `negadecimal`, would give zero.
`public int decimalValue()`
Returns the decimal equivalent of this negadecimal number.
`public boolean equals(NegadecimalNumber ndn)`
Returns `true` if this number and `ndn` have the same value. Necessary for unit testing.
`public String toString()`
Returns the string representation of this negadecimal number.

This class contains a `main` method. When executed, this method acts as a simple calculator, using the negadecimal number system. The calculator's "display" shows the (negadecimal) number currently in the calculator (`0` when the program first starts up. Subsequent operations use this number and, in the case of a binary operation, the number entered by the user, to compute a new number to display.

In the descriptions below, the word integer will refer to an ordinary `int` value. The term negadecimal number (ndn for short) will mean a string composed of decimal digits only.

The user may type in any of the following expressions. After entering an expression, the calculator performs the requested operation and displays the result. If the user enters an illegal number (a blank line, or something not composed entirely of digits), the word `Error` will be displayed instead.

 `ndn` Replaces the number currently in the display with this new number `ndn`. `+ ndn ` Adds `ndn` to the current display. `- ndn ` Subtracts `ndn` from the current display. `* ndn ` Multiplies the current display by `ndn`. `/ ndn ` Divides the current display by `ndn`. Displays `Error` if `ndn` is zero. `% ndn ` Gives the remainder when dividing the display by `ndn`. `~ ` Computes the negative the display, that is, zero minus the number in the display. `?` Shows the decimal value of the displayed negadecimal number, then redisplays the negadecimal number. This is a way of "peeking" at the decimal value of a number without modifying the current value in the calculator. `decimal integer ` Replaces the number currently in display with the negadecimal equivalent of the decimal number entered by the user. This is the only expression for which the number entered by the user is a decimal value. `clear` Clears any errors and replaces whatever is in the display with 0. `quit` Quits the program.

Your "calculator" will remember the last number computed (initially zero, when you start the program). In each of the above expressions,

• The user may (or may not) put spaces before or after numbers, and before or after operators.
• The user may enter leading zeros (such as` 00191`); however, your calculator should not give results with leading zeros.
• If at any time the calculator displays `Error`, the user must enter `c` ("clear") before anything else can be done.
• The commands `decimal`, `clear`, and `quit` can each be abbreviated to a single letter.

The Negadecimal calculator should have (at least) the following methods:

`public String evaluate(String s )`
Takes a string that may have been entered by the user (or may have come from our test methods), and
1. Finds the various parts of the string (for example, first operand, operator, second operand).
2. Tries to parse the input, that is, recognize what kind of command it is. If the input does not appear to be a legal command, return an error message (possibly just "Error").
3. Calls one of the above methods to perform the arithmetic.
4. Returns the result as a string.

You may find it useful to write "helper functions" for each of steps 1, 2, and 3, otherwise you may end up with a very long function.
`public void REPL()`
This method implements a basic Read-Evaluate-Print-Loop. It should:
• Read an input from the user,
• This is a good place to check for `q` (quit).
• Evaluate it, using the above `evaluate` function,
• Print the result (either a negadecimal number, or an error message), and
• Loop (do it again). Or, instead of a loop, you could make a recursive call to `REPL`.

This should be the only function that does any input/output.

`public static void main(String[] args)`
This is the method that begins the program. All it should do is create an instance of `NegadecimalCalculator` and call its `REPL` method.

Example (I am using "`Compute:`" as a prompt; all numbers except the response to `?` are negadecimal numbers):

`Compute: 195195Compute: ?195 (decimal 15)Compute: +105Compute:  - 20185Compute: helloErrorCompute: c0Compute: quitDone.`

## Programming hints

• Inside the `NegadecimalNumber` class, you can do the arithmetic using integers. Why try to multiply two strings?
• It's better to have many short functions than a few long ones. My `REPL` function is very short, because most of the work is done in `evaluate(string)`.
• Rule of thumb: You should be able to see each complete function on the screen, without scrolling.
• Characters in Java are numbers, and you can do arithmetic on them; this will give you an `int` result.
• You can "index" into a String with the `charAt(i)` method. For example, `s.charAt(0)` will return the first character in string `s`.
• The most critical things to write first are the constructors, and the methods `toString` and `equals`.
• You can test if a character `ch` is a digit by calling the method `Character.isDigit(ch)`.
• You can throw an exception by saying `throw newTypeOfException();`, where`TypeOfException`is, for example, `IllegalArgumentException`.
• You can catch an exception by saying
``````try {
code that might throw an exception of type TypeOfException
} catch (TypeOfException e) {
what to do now that you've caught it
}``````

# JUnit testing

Let Eclipse do most of the work for you!

After you have stubs for all your methods in a class, make sure the class is selected, then go to `File → New → JUnit Test Case`. Make sure "New JUnit 4 test" and "setUp()" are selected. Don't click `Finish`! Click `Next>` and select the methods you want unit tests for. Then you can click `Finish`.

All of the methods are set up to call `fail("Not yet implemented")`. Replace these calls with more meaningful calls. The most commonly used methods are:

• `assertEquals(expected_result, call_of_method)`
• `assertTrue(call_of_method)`
• `assertFalse(call_of_method)`

For method calls that you expect to throw an assertion, you need to modify the `@Test` annotation to read
`@Test(expected=TypeOfException.class)`
and inside the test method, you don't need to call any "assert" methods, just call the method you want to throw an exception.

# Due date

Turn your assignment in to Canvas before 6am Friday, November 7.