How many times is the following statement in the loop executed?
while (false) statement;
Answer:
Never.
Self Check 6.2
What would happen if RATE was set to 0 in the main method of
the InvestmentRunner program?
Answer:
The waitForBalance method would never return due to an infinite loop.
Common Error: Infinite Loops
Example:
int years = 0;
while (years < 20)
{
double interest = balance * rate / 100;
balance = balance + interest;
}
Example:
int years = 20;
while (years > 0)
{
years++; // Oops, should have been years--
double interest = balance * rate / 100;
balance = balance + interest;
}
Loops run forever – must kill program
Common Error: Off-by-One Errors
Off-by-one error: a loop executes one too few, or one too many, times
Example:
int years = 0;
while (balance < 2 * initialBalance)
{
years++;
double interest = balance * rate / 100;
balance = balance + interest;
}
System.out.println("The investment reached the target after " +
years + " years.");
Should years start at 0 or 1?
Should the test be < or <=?
Avoiding Off-by-One Error
Look at a scenario with simple values:
initial balance: $100
interest rate: 50%
after year 1, the balance is $150
after year 2 it is $225, or over $200
so the investment doubled after 2 years
the loop executed two times, incrementing years each time Therefore: years must start at 0, not at 1.
interest rate: 100%
after one year: balance is 2 * initialBalance
loop should stop
Therefore: must use <
Think, don't compile and try at random
for Loops
Example:
for (int i = 1; i <= n; i++)
{
double interest = balance * rate / 100;
balance = balance + interest;
}
Use a for loop when a variable runs from a starting value to an ending
value with a constant increment or decrement
sum = 0;
for (i = 1; i <= 10; i++);
sum = sum + i;
System.out.println(sum);
Common Loop Algorithm: Computing a Total
Example — keep a running total: a variable to which you add each input value:
double total = 0;
while (in.hasNextDouble())
{
double input = in.nextDouble();
total = total + input;
}
Common Loop Algorithm: Counting Matches
Example — count how many uppercase letters are in a string:
int upperCaseLetters = 0;
for (int i = 0; i < str.length(); i++)
{
char ch = str.charAt(i);
if (Character.isUpperCase(ch))
{
upperCaseLetters++;
}
}
Common Loop Algorithm: Finding the First Match
Example — find the first lowercase letter in a string:
boolean found = false;
char ch = '?';
int position = 0;
while (!found && position < str.length())
{
ch = str.charAt(position);
if (Character.isLowerCase(ch)) { found = true; }
else { position++; }
}
Common Loop Algorithm: Prompting Until a Match is Found
Example — Keep asking the user to enter a positive value < 100 until the user provides a correct input:
boolean valid = false;
double input;
while (!valid)
{
System.out.print("Please enter a positive value < 100: ");
input = in.nextDouble();
if (0 < input && input < 100) { valid = true; }
else { System.out.println("Invalid input."); }
}
Common Loop Algorithm: Comparing Adjacent Values
Example — check
whether a sequence of inputs contains adjacent duplicates such as 1 7 2 9 9 4 9:
Common Loop Algorithm: Processing Input with Sentinel Values
Example — process a set of values
Sentinel value: Can be used for indicating the end of a data set
0 or -1 make poor sentinels; better to use Q:
System.out.print("Enter value, Q to quit: ");
String input = in.next();
if (input.equalsIgnoreCase("Q"))
We are done
else
{
double x = Double.parseDouble(input);
. . .
}
Loop and a Half
Sometimes termination condition of a loop can only be evaluated in the middle of
the loop
Then, introduce a boolean variable to control the loop:
boolean done = false;
while (!done)
{
Print prompt
String input = read input;
if (end of input indicated)
done = true;
else
{
Process input
}
}
ch06/dataset/DataAnalyzer.java
ch06/dataset/DataSet.java
Program Run:
Enter value, Q to quit: 10
Enter value, Q to quit: 0
Enter value, Q to quit: -1
Enter value, Q to quit: Q
Average = 3.0
Maximum = 10.0
Self Check 6.5
How do you compute the total of all positive inputs?
Answer:
double total = 0;
while (in.hasNextDouble())
{
double input = in.nextDouble();
if (value > 0) total = total + input;
}
Self Check 6.6
What happens with the algorithm in Section 6.3.5, Comparing Adjacent Values, when no input is provided at
all? How can you overcome that problem?
Answer:
The initial call to in.nextDouble() fails, terminating the program. One solution is to
do all input in the loop and introduce a Boolean variable that checks whether the
loop is entered for the first time.
double input = 0;
boolean first = true;
while (in.hasNextDouble())
{
double previous = input;
input = nextDouble();
if (first) { first = false; }
else if (input == previous) { System.out.println("Duplicate input"); }
}
Self Check 6.7
Why does the DataAnalyzer class call in.next and not in.nextDouble?
Answer:
Because we don't know whether the next input is a number or the letter Q.
Self Check 6.8
Would the DataSet class still compute the correct maximum if you
simplified the update of the maximum field in the add method
to the following statement?
if (maximum < x) maximum = x;
Answer:
No. If all input values are negative, the maximum is also negative.
However, the maximum field is initialized with 0. With this
simplification, the maximum would be falsely computed as 0.
Nested Loops
Create triangle shape:
[]
[][]
[][][]
[][][][]
Loop through rows:
for (int i = 1; i <= n; i++)
{
// Make triangle row
}
Make triangle row is another loop:
for (int j = 1; j <= i; j++)
r = r + "[]";
r = r + "\n";
How do you use a random number generator to simulate the toss of a coin?
Answer:
int n = generator.nextInt(2); // 0 = heads, 1 = tails
Self Check 6.12
Why is the NeedleSimulator program not an efficient method for
computing π?
Answer:
The program repeatedly calls Math.toRadians(angle). You could simply
call Math.toRadians(180) to compute π.
Using a Debugger
Debugger: a program to execute your program and analyze its run-time behavior
A debugger lets you stop and restart your program, see contents of variables,
and step through it
The larger your programs, the harder to debug them simply by inserting print commands
Debuggers can be part of your IDE (e.g. Eclipse, BlueJ) or separate programs (e.g. JSwat)
Three key concepts:
Breakpoints
Single-stepping
Inspecting variables
The Debugger Stopping at a Breakpoint
Inspecting Variables
Debugging
Execution is suspended whenever a breakpoint is reached
In a debugger, the program runs at full speed until it reaches a breakpoint
When execution stops you can:
Inspect variables
Step through the program a line at a time
Or, continue running the program at full speed until it reaches the next
breakpoint
When the program terminates, the debugger stops as well
Breakpoints stay active until you remove them
Two variations of single-step command:
Step Over: skips method calls
Step Into: steps inside method calls
Single-step Example
Current line:
String input = in.next();
Word w = new Word(input);
int syllables = w.countSyllables();
System.out.println("Syllables in " + input + ": " + syllables);
When you step over method calls, you get to the next line:
String input = in.next();
Word w = new Word(input);
int syllables = w.countSyllables();
System.out.println("Syllables in " + input + ": " + syllables);
However, if you step into method calls, you enter the first line of the countSyllables
method
public int countSyllables()
{
int count = 0;
int end = text.length() - 1;
. . .
}
Self Check 6.13
In the debugger, you are reaching a call to System.out.println. Should
you step into the method or step over it?
Answer:
You should step over it because you are not interested in debugging the
internals of the println method.
Self Check 6.14
In the debugger, you are reaching the beginning of a long method with a couple
of loops inside. You want to find out the return value that is computed at the
end of the method. Should you set a breakpoint, or should you step through the
method?
Answer:
You should set a breakpoint. Stepping through loops can be tedious.