Wyo Java Ch. 6 Lecture Notes
Objective #1: Explain the importance of loops in programs.
- In order to write a non-trivial computer program, you almost always need to use one or more loops. Loops allow your program to repeat groups of statements a specified number of times. Loops are classified as a type of iteration (or repetition) structure.
- It is important to be aware of how many iterations a given loop is expected to perform. If a loop does not iterate a finite number of times, it is considered to be an infinite loop. Rarely would a programmer ever intentionally incorporate an infinite loop into a program, however it is easy to do so by mistake.
- It is important to write out and trace loops carefully to avoid an off-by-one bug (OBOB). An off-by-one bug is a logic mistake caused by a loop iterating one extra time.
Objective #2: Use for loops.
- A for loop always executes a specific number of iterations. Use a for loop when you know exactly how many times a set of statements must be repeated.
- A for loop is called a determinate or definite loop because the programmer knows exactly how many times it will iterate. You can mathematically determine the number of iterations by deskchecking the logic of the loop.
- After the keyword, for, a set of parentheses is necessary with three expressions as parameters.
for(initializing expression; control expression; step expression)
{
one or more statements
}
- The initializing expression sets the counter variable for the loop to its initial value.
- The control expression ends the loop at the specified moment.
- The step expression (or incrementing expression) changes the counter variable,effectively determining the number of iterations. The counter variable often increments by one, but it may increment, decrement, or count in other ways.
- The one or more statements in the curly braces is the body of the loop
- Example:
for (i = 1; i <= 3; i++)
{
System.out.println(i);
}
- It is possible to initialize the loop variable within the initializing expression as in:
for (int i = 0; i < 10; i++)
{
System.out.println(i);
}
However the scope of i is
the loop and i cannot
be used outside of the loop even if the loop is written without curly braces.
In fact,
curly braces can be used to narrow the scope of a variable in non-loop situations.
In this example,
int outside = 5;
{
int inside = outside;
}
outside = inside;
an error occurs since the variable inside cannot
be used outside of the set of curly braces. Since inside is
declared inside of
the curly braces, its scope
is only the area within the curly braces.
- You can increment the loop variable by more than 1 if you wish. In the following loop, the loop variable is incremented by 3 on each iteration:
for (i = 1; i <= 9; i = i + 3)
{
System.out.println(i);
}
Of course, the compound operator could be used with i += 3 replacing the i = i + 3 incrementing expression.
It is a common error for students to use:
for (i = 1; i <= 9 ; i + 3)
instead of the required
for (i = 1; i <= 9; i = i + 3)
- Some programmers use a for loop like,
for (;;)
{
System.out.println("Enter a number: ");
//user inputs a value into userInput w/ JOptionPane or BufferedReader
if (userInput != -99)
{
runningTotal += userInput;
}
else
{
break;
}
}
in which case the infinite for loop will run until the break condition is met. Note that technically the initializing, control, and incrementing expressions of a for loop are optional. However, this is poor coding since it can lead to logical errors and you should avoid using break statements and infinite loops when possible.
- Like if statements and other kinds of loops, the curly braces are not required with a for loop if there is only statement in the body of the loop. However, it is good style to always use curly braces.
Objective #3: Use while loops.
Objective #4: Use do while loops.
- AP students are not required to be able to write or evaluate do while loops on the AP exam. However they can be used in a student's answer on the Free Response section of the exam.
- As with a while loop, a do while loop does not necessarily iterate a specified number of times. However, it is guaranteed that a do while loop will iterate at least one time because its control expression is placed at the end of the loop. This loop is useful when you want to guarantee at least one iteration of the loop.
- Like a while loop, a do while loop is considered to be an indeterminate or indefinite loop.
- A do while loop is considered to be a bottom-checking (or posttest) loop, since the control expression is located after the body of the loop after the while keyword. A do while loop is guaranteed to iterate at least once even if the control expression evaluates to FALSE.
Objective #5: Use the break and continue statements with loops appropriately.
- A break statement is used to stop the execution of a loop immediately and to continue by executing the statement that comes directly after the loop. Only use the break statement when it is not practical to control the execution of a loop with its control expression. That is, only use a break statement when absolutely necessary.
while (num != -99)
{
user inputs a value for num here
if (num == -99)
{
break;
}
sum += num;
}
however it would be better to write this loop to avoid the use of a break statement if possible since break statements found within a loop can be difficult to pick out by those who read over your code. This version of the same loop would be better for clarity.
num = 0;
while (num != -99)
{
sum += num;
user inputs a value for num here
}
- A continue statement is used to stop the execution of the statements in the loop's body on that particular iteration and to continue by starting the next iteration of the loop.
In the following example, all inputed positive numbers less than or equal to 100 are subtotaled. If a negative value is inputed, it is not added to the subtotal but rather the loop continues with the next iteration. Any value greater than 100 could be entered to terminate the loop.
while (num <= 100)
{
user inputs a value for num here
if (num < 0)
{
continue;
}
sum += num;
}
Objective #6: Use nested loops effectively when appropriate.
Objective #7: Use flag variables and sentinel values to control indeterminate loops.
- A sentinel value is a special value that is used to cause an indeterminant loop to terminate. Often sentinel values are inputed by a user to indicate the end of input. For example, the sentinel value of -99 is used in the loop below to terminate the loop which calculates a bowling average. It should be noted that the -99 is being used as a sentinel value since it is impossible in the sport of bowling to bowl a score of -99. Therefore the sentinel value will not mistakenly be entered as an inputed bowling score.
System.out.println("Enter a bowling score (-99 to quit): ");
user inputs a value for score here
while (score != -99)
{
sum += score;
numGames++;
System.out.println("Enter a bowling score (-99 to quit): ");
user inputs a value for score here
}
System.out.println("Your average is " + (double) sum / numGames);
- A flag variable is a special variable that is used to control an indeterminate loop. A flag variable is usually a boolean variable that is assigned true or false. Some old-fashioned programmers use an int variable and use the value 1 for true and 0 for false.
boolean choseBook= false;
boolean choseCD = false;
do
{
System.out.println("1 Book");
System.out.println("2 CD");
System.out.println("3 Exit");
System.out.println("Enter a menu option: ");
user inputs a value for menuChoice here
if (menuChoice == 1)
{
System.out.println("You chose book.");
choseBook = true;
}
else if (menuChoice == 2)
{
System.out.println("You chose cd.");
choseCD = true;
}
}
while (menuChoice != 3 && choseBook != true && choseCD != true);
Objective #8: Identify loop invariants.
- A loop invariant is an expression
that is always true at the top of a loop. It is an expression that is true
every time the loop iterates including the last time around the loop even
if
the
loop's
control
expression is false.
- Consider the loop
int sum = 10;
for (int i = 2; i < 12; i += 2)
{
System.out.println(i);
sum += i;
}
The following are loop invariants for the loop above:
i is always even
i <= 12
i is positive
sum > i
The following is not a loop invariant:
i < 12 since i is equal to 12 on the last attempted
iteration)
- Another example...
int temp = 0;
int num = 1;
while (num < 100)
{
num += 2;
System.out.println(num);
temp = num;
num = -5;
num = temp;
}
The following are loop invariants in the code segment above:
num is always odd
num < 102
num > -6
num > 0 (since num is greater than zero every
time the computer is at the top
of the loop, even on the last iteration)
The following is not a loop invariant:
num < 100 (since num is 101 on the last evaluation of the control expression
when it evaluates to false)
Objective #9: Use random number generation to create
simulations.
- it is technically impossible to create a truly random value with a computer since any available built-in method or process for creating a random value relies on some determinate mechanism such as the computer's system clock. So it is proper to call these values pseudorandom rather than random.
- The static method named random in the Math class can be used to create a random decimal value that is greater than or equal to 0.0 and less than 1.0. You can manipulate this returned value by turning it into an integer or "spreading out" the range of possible values. Here are some examples using the following notation. If x is a number in the range (0, 10) then x is between 0 and 10 exclusive, not including the endpoints. The notation [0, 10] means between or including 0 and 10. The notation [0, 10) means 0 <= x < 10.
x = Math.random() * 6; // 0 <= x < 6
x = (int) (Math.random() * 6); // 0 <= x <= 5
x = (int) (Math.random() * 6) + 1; // 1 <= x <= 6
x = (int) (Math.random() * 10) - 4; // -4 <= x <= 5
be careful to use the extra set of parentheses in the examples above since
x = (int) Math.random() * 6 + 1; // always equals one
- The Math.floor method could be used instead of typecasting with the (int) cast operator as in
x = Math.floor(Math.random() * 6) + 1
- A general formula to use for generating a random integer over a range of values is
(int) (Math.random() * (HI - LO + 1)) + LO
where HI is the highest integer and LO is the lowest integer in the desired range of integer values.
- If you wanted something to occur based on a probability of say 40% in a Java game or simulation, then you could use the Math.random method like this
if (Math.random() < 0.4)
{
System.out.println("The event occurred.");
}
else
{
System.out.println("The event did not occur.");
}
- The Math.random value does not need to be seeded like some corresponding methods or functions in other computer languages.
- You can also create random numbers by using the Random class of the Java API library. This method is not covered on the AP exam however.
1 import java.util.Random;
2
3 public class RandomNumbers
4 {
5 public static void main(String[] args)
6 {
7 Random dice = new Random();
8 int diceRoll = dice.nextInt(6) + 1;
9 }
10 }
- On line #7 of the example above, the object named dice with the type Random is declared. The Random class's nextInt method is then used with an argument of 6 on line #8 to generate a pseudorandom number between or including 0 and 5. Since 1 is added to that value, a resulting value between or including 1 and 6 is stored into the int variable named diceRoll. To use a Random object, you must import the Random class with the import statement in line #1.
- The nextDouble method of the Random class can be used to generate pseudorandom floating-point numbers. The statement
double randomDecimal = dice.nextDouble();
would generate a random decimal value between 0 (inclusive) and 1 (exclusive).
- When you instantiate a Random object
you may specify a seed
value with
an "other" constructor.
Using the instantiation statement
Random dice = new Random(1);
rather than
Random dice = new Random();
causes the same sequence of pseudorandom values to be generated with nextInt or
nextDouble. Normally, you would not want a
game or a simulation program that uses random numbers to use the same exact
sequence of random numbers
every time the program executes. It would be boring and predictable for a
game to always play the same way. However, while your debugging a program
or testing the effect of other conditions and parameters, you may want to
control the sequence of random values so that the same exact sequence is used.
This helps you focus on the bug that you're trying to fix or focus on the
effect of the parameter or conditions that you are changing. Any positive
integer can be used in the constructor as the seed value.