Table of Contents
We advise the students to program according to usual Java conventions. The document Java Coding Guidelines presents a brief introduction to the most important conventions, as well as instructions on how to configure Eclipse according to them.
A debugger is a program to test other programs in a controlled way. A debugger allows finding errors in programs (bugs) and help to understand them.
Common functionalities of a debugger:
Run a program step by step (this is, the program will execute one source code statement and then wait for further instructions).
Stop the execution of a program at a given line of source code and wait for further user instructions.
Allow to inspect the values of the program variables while its execution is stopped.
The Eclipse IDE includes a nice Java debugger that can help you to find and fix bugs in your programs.
The following program computes the value of pi with the desired precision (the number of desired decimal places is passed as a command argument).
import java.math.BigDecimal; import java.math.MathContext; public class PiCalc { private int numDigits; private MathContext mc; public PiCalc(int numDigits) { this.numDigits = numDigits; mc = new MathContext(numDigits); } public BigDecimal compute() { BigDecimal pi = new BigDecimal(0); BigDecimal limit = new BigDecimal(1).movePointLeft(numDigits); boolean stop = false; for (int k = 0; !stop; k++) { BigDecimal piK = piFunction(k); pi = pi.add(piK); if (piK.compareTo(limit) < 0) { stop = true; } } return pi.round(mc); } private BigDecimal piFunction(int k) { int k8 = 8 * k; BigDecimal val1 = new BigDecimal(4); val1 = val1.divide(new BigDecimal(k8 + 1), mc); BigDecimal val2 = new BigDecimal(-2); val2 = val2.divide(new BigDecimal(k8 + 4), mc); BigDecimal val3 = new BigDecimal(-1); val3 = val3.divide(new BigDecimal(k8 + 5), mc); BigDecimal val4 = new BigDecimal(-1); val4 = val4.divide(new BigDecimal(k8 + 6), mc); BigDecimal val = val1; val = val.add(val2); val = val.add(val3); val = val.add(val4); BigDecimal multiplier = new BigDecimal(16); multiplier = multiplier.pow(k); BigDecimal one = new BigDecimal(1); multiplier = one.divide(multiplier, mc); val = val.multiply(multiplier); return val; } public static void main(String[] args) { if (args.length != 1) { System.err.println("One command-line argument expected: number of " + "digits."); } else { PiCalc piCalc = new PiCalc(Integer.parseInt(args[0])); System.out.println(piCalc.compute()); } } }
Take a look at its source code without paying too much attention to its details and answer the following questions.
Can you describe the program flow? This is, what methods are invoked and in which order? Is there any method that is being executed more than once?
Justify why the class BigDecimal
is used instead of the native Java types float
or
double
. Look for external documentation to back up
your answer.
Import the program into Eclipse and run it several times with varied precisions. Note how the program takes more and more time to execute as you ask for higher precisions (in the next section you will understand why is that).
Use the Eclipse debugger to understand how the program works. Set
a breakpoint in the first line of the method
compute()
(menu Run / Toggle
Breakpoint). Run the program in debug mode, using
Debug instead of
Run. The program will begin its execution and
will stop at your breakpoint.
You will be asked to change the Eclipse perspective to the
Debugging Perspective, which will allow you to
control and obtain information about the ongoing debugging
session. You will be able to see your source code, along with a
marker on the line that is going to be executed next. You can also
see the values of your program variables (at first, only
this
is shown, which is the object with the method
where the breakpoint is; if you unfold it, you will be able to see
the values of all its attributes). You can also see the Console.
Now that the program is waiting at the breakpoint, you can resume its execution in several ways:
Option Run / Resume: resume the program execution until it finishes or until a breakpoint is reached.
Option Run / Step Into: execute the next line of code. If this line is a method invocation, the program will stop executing at the first line of code inside that method, so you can execute the program step by step.
Option Run / Step Over: execute the next line of code. If this line is a method invocation, the program will execute the whole method normally and then stop once it returns. This is very useful to understand the general flow of the program without getting into the details of each method.
Option Run / Step Return: execute the code in the current method until it gets to a return statement.
You can also cancel the debugging mode by using the option Run / Terminate.
Debug the program using 10 as its command line argument. Count the number of iterations performed on the loop inside the method compute() before getting the final value of pi. Repeat this for bigger arguments. What can you say about the time it takes to execute the program as a function of its argument?
In a new debugging session, keep track of the value of the variable piK on each loop iteration. How is this value changing with each iteration of the loop?
What is the role of the limit
variable in the
program? Run additional debugging sessions if you need to.
What is the mathematical expression that the program is using to calculate the value of pi? You can answer this question by thinking about the source code above and using the debugger.
Write a new Java program to calculate the area of a circle knowing
it radius. This program will have a main
method that
will receive as its arguments the decimal places of pi for the
calculation of the solution and the radius of the circle. The
program must write the calculated area to its standard output.
The program must use the class PiCalc
presented above
to generate a suitable value of pi for its calculations. It must
also use the class BigDecimal.
Write a new Java program to calculate the sum of the areas of
several circles, knowing their radii. The program will have a
main
method with the following arguments: the desired
precision on pi and one or more radii values (one per circle). The
program must write the solution to the standard output.
This program must use the class from the previous section and BigDecimal.