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:

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.
Saves the integer (decimal) parameter in an instance variable.

Returns a new negadecimal number which is the result of subtracting ndn from "this" negadecimal number.
Returns a new negadecimal number which is the result of multiplying ndn and "this" negadecimal number.
Returns a new negadecimal number which is the result of dividing "this" negadecimal number by ndn. Throws an ArithmeticException if ndn is zero.
Returns a new negadecimal number which is the remainder after dividing "this" negadecimal number by ndn. Throws an ArithmeticException if ndn is zero.
public int decimalValue()
Returns the decimal equivalent of this negadecimal number.
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: 195
195
Compute: ?
195 (decimal 15)
Compute: +10
5
Compute: - 20
185
Compute: hello
Error
Compute: c
0
Compute: quit
Done.

## 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();, whereTypeOfExceptionis, 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.