Assignment 04

Task

Implement a primitive calculator in order to learn how to define your own instance methods.

Textbook: 3.5; 6.5
New concepts: Instance methods (and methods in general, including parameters and return types); generating random numbers.

Steps

You are going to write an integer-based calculator that prints a summary of each of its operations to the screen. You can think of this as a calculator with an audit trail. You will then informally test your calculator with a short program.

Step 1: Methods

Write a class named PrintingIntCalculator. Your class must have exactly this name. It should contain the following methods:

Tamarin will be calling your methods directly, so each method must have exactly the signature given above. (You can rename the a and b parameters, but that is the only allowed change.)

You will need to provide a {body} for each of these methods that does the appropriate operation with the two passed values and returns the correct result. Your calculator should do int math, so no casting or doubles are needed. Each method should also print out a single line containing the expression and result of what it did (sort of like you did in A01a). For example, if I put this code in my main method:

  PrintingIntCalculator calc = new PrintingIntCalculator();
  int result = calc.add(3, 4);

then result should contain the value 7 and the following line should have appeared in my output:

  3 + 4 => 7

The random method should return a random value that is between a and b inclusive. For example, after calling:

  int val = calc.random(1, 3);

val should contain either 1, 2, or 3. When printing to the screen for this method, use a format like this:

  random(1, 3) => 2

(For this assignment, you can assume that the caller of this method will always give the lower value first (as a) and then the higher value (as b) of the requested random range. We'll learn more about error-checking input to methods later.)

Step 2: Main method

Now write a class named UsernameA04. In a main method in that class, print the results of the following expression:

  (30 - 4 + 15 * 20 / 10) % random(1, 10)

Use one instance of your PrintingIntCalculator class to perform all the operations of this expression. (Make sure you perform the operations in the normal precedence order.) You may use intermediate variables (as I did above when I stored the result of adding two numbers into a variable named result.)

At the end of your calculations, print your final result on its own line.

Sample Output

Here's what I got when I ran my main method. Note that, since there is some random number generation involved, your final result should vary each time you run your program.

15 * 20 => 300
300 / 10 => 30
30 - 4 => 26
26 + 30 => 56
random(1, 10) => 3
56 % 3 => 2

Result: 2

Running this program once or twice is not the only testing you should do. For example, make sure that your random method really returns every possible value in the specified range and no values outside the range. This might take you a while to check with 1 to 10. 4 to 6 might be a better range.

What to Submit

You are going to submit both your UsernameA04 and PrintingIntCalculator classes.

Normally, each Java class should be in its own file. However, Tamarin only takes a single file per submission. So you are going to move your PrintingIntCalculator class into your UsernameA04.java file. Paste the entire PrintingIntCalculator class after the last } of the UsernameA04 class. (Please make sure you don't put one class within another!)

Java will allow you to have only 1 public class per file though, so you also need to remove the word public from the PrintingIntCalculator class. (Leave the public modifier on all your methods, though.)

So, your UsernameA04.java file should now be structured like this:

public class UsernameA04 {
  //... your main method in here ...
}

class PrintingIntCalculator {
  //... your 6 calculator methods in here ...
}

You may want to try deleting all your .class files, and then compiling and running your UsernameA04.java one more time before you submit it, just to make everything still works correctly.

Then, upload your complete UsernameA04.java file to Tamarin.

Grading [4 points]

1 - Compiles
Your program compiles successfully (no errors)
2.5 - PrintingIntCalculator
Class has correct name (0.5, required for remaining tests). Has 5 math methods with names and signatures exactly as specified above, which all return the correct result and print their expressions and results to the screen (1.0). Has the requested random method which returns an evenly-distributed random number between its two arguments (inclusive) and prints a corresponding expression to the screen (1.0).
0.5 - main method in UsernameA04
Correctly calculates the requested expression, printing the final result to the screen on its own line.

FAQs

Demo Code
From Section 001: MyClass.java.

This file contains two classes. The first class is a program (that was on the whiteboard in lab) that calls the methods defined in the second class (which I wrote on the computer). This file also shows how you can put two classes in one file--which is not normally recommended practice but is necessary in order to submit more than one class to Tamarin.

What goes into the methods of the PrintingIntCalculator class?
This is where you define the behavior of the methods. So you're going to use some math operators here, like this:
  public int add(int a, int b) {
    int result = a + b;
    //[print expression to screen here, using a and b and result]
    return result;
  }

So it is in the method body that you do the calculation and the printing. You do not need to create a PrintingIntCalculator or call any of the methods here--you're going to do that later in your other class's main method.

You need to do the printing before you return the final value because the method stops running as soon as you hit a return statement. Note that your method will not even compile until you return some sort of int value--since that is what you declared your method's return type to be.

Should I declare one or more variables before all my methods in the PrintingIntCalculator class?
No. Declaring a variable outside all of your other methods is how you create an instance variable--something we won't deal with until the next assignment. To prevent certain common bugs and errors, you should always declare a variable within (local to) a method--unless you have some good reason to make it an instance variable.

In this assignment, the PrintingIntCalculator has no internal state. That is, it does not keep a running total or result (unlike the PiggyBank discuused in lecture). So there is no data that more than one method needs access to. So you do not need any instance variables.

But if the calculator doesn't keep track of the result so far, how do I compute the expression?
You'll use a variable within your main method to do this. For example, suppose I want to compute 2 * 3 + 4. In my main method, I would do this:
  PrintingIntCalculator calc = new PrintingIntCalculator();
  int soFar = calc.multiply(2, 3);
  soFar = calc.add(soFar, 4);
  System.out.println("Result = " + soFar);

This should produce the following output:

2 * 3 => 6
6 + 4 => 10
Result = 10
How did that random number generation trick work again?
One way to generate a random number is to use Math.random(). For example, you can generate an int between 1 and 5 (inclusive) like this:
  int rnd = (int)(Math.random() * 5) + 1;

To generate an int between -3 and 6 would look like this:

  int rnd = (int)(Math.random() * 10) - 3;

The general form I'm using here is:

  int rnd = (int)(Math.random() * range) + shift;

where range is the number of distinct random ints you want to generate (so 5 for 1-to-5, and 10 for -3-to-6) and shift is basically where you want to start counting (so 1 for 1-to-5, and -3 for -3-to-6).

Remember that you will need to think even more abstractly, since your random method is supposed to work in terms of a and b so that is can produce a value from a different random range each time it is called.

The textbook briefly describes how to use java.util.Random to generate random ints. (You can also look this class up in the API.) You may use that approach instead of using Math.random(), if you prefer.

Okay, so the calculator's random method is supposed to generate a random number in terms of a and b, but how do I do that?
You'll have to figure out a formula to do this. Don't worry, this is fairly simple to do if you just think about how you figure this out yourself. Here are some examples:
abrange of random valuessize of rangeb - astart of range (shift)
15{1,2,3,4,5}541
36{3,4,5,6}433
-24{-2,-1,0,1,2,3,4}76-2

So, if you're using the formula discussed above, you need to figure out the range and shift in terms of a and b. As you can see here, the shift from 0 is the same as the start of the range, which is the same as a. Computing the range is trickier. It's not just b. (b - a) is close, but is one off.... (You should be able to figure it out from here.)