Chapter 5. Repetition

One of the great virtues of computers is that they will repeat mindless tasks without complaint. To facilitate such repetition, Java includes statements types called loops, which allow a program to specify some sequence of instructions that should be repeated.

5.1. The while loop

Java has a few categories of loops, and the most fundamental of these is the while loop. The while loop enables you to specify that some sequence of statements should be repeated as long as some condition is true (i.e., while the condition holds) . The template for a while loop looks like the following.

while(<thisIsTrue>) {
    <statementsToRepeat>
}

You include the word while, with a true/false expression in parentheses (the parentheses are required), followed by a set of braces including the lines you want to repeat. The parenthesized expression is called the condition of the loop. The part between the braces is the loop's body.

When the computer reaches a while loop, it tests the condition inside the parentheses to determine whether it is true. If so, it executes the body (between the braces) and then checks the condition again. It repeatedly checks the condition and executes the body, until finally it finishes the body and the condition turns out to be false. Each execution of the loop's body is called an iteration. Once the condition turns out to be false, the computer continues to the first statement following the body (after the closing brace). (If the condition never held in the first place, the computer skips past the body immediately, with no iterations.) Figure 5.1 illustrates this process.

Figure 5.1: A flowchart for the while statement.

To see an example of a while loop, let's look back to our DrawSquare program (Figure 4.1). That program was a bit repetitive: We repeated the same two lines four times, once for each side. We could replace lines 10 to 16 with a while loop, with each iteration of the loop drawing a single side of the square. Figure 5.2 contains such a program.

Figure 5.2: The DrawSquareLoop program.

  1  import turtles.*;
  2  
  3  public class DrawSquareLoop extends TurtleProgram {
  4      public void run() {
  5          double sideLength;
  6          sideLength = this.readDouble();
  7  
  8          Turtle boxTurtle;
  9          boxTurtle = new Turtle(100 - sideLength / 2, 100 - sideLength / 2);
 10          int drawn// counts how many sides are complete
 11          drawn = 0; // so far none are complete
 12          while(drawn < 4) {
 13              boxTurtle.forward(sideLength);
 14              drawn = drawn + 1; // we've completed one more side
 15              boxTurtle.right(90);
 16          }
 17          boxTurtle.hide();
 18      }
 19  }

The computer would execute the DrawSquareLoop program as follows.

  1. Lines 5–9: These lines are the same as before: They determine the size of the square and initialize the turtle.

  2. Lines 10–11: The computer creates a variable drawn to count how many sides of the square boxTurtle has drawn. Because boxTurtle hasn't drawn any sides yet, the program initializes drawn to 0.

  3. Line 12: The computer checks whether the condition drawn < 4 holds. It is, so the computer proceeds to execute each of the statements in the braces.

  4. Line 13: The computer tells boxTurtle to move forward sideLength pixels.

  5. Line 14: The computer now reassigns drawn to a new value: In particular, it is assigned to the value of drawn + 1. Since drawn is currently assigned to the value 0, the value of drawn + 1 is 1, and so 1 is the value now assigned to the drawn name.

    Notice the peculiarity of this line. If this were an algebra class, you'd look at this as an equation, cancel drawn from both sides, and end up with 0 = 1. But in Java, the equal sign represents assignment, not equality as in algebra. So the computer doesn't think about the relationship between the two sides: It simply evaluates the right-hand side first, and then it assigns the left-hand variable to reference whatever result falls out.

  6. Line 15: The computer tells boxTurtle to turn 90° clockwise, so that boxTurtle now faces south.

  7. Line 16: Having reached the end of the while loop, the computer proceeds to the top of the loop again to check the condition again, in line 12.

  8. Lines 12–16: The computer checks whether the condition drawn < 4 still holds. Since drawn is 1, it is does. Hence we proceed: The computer tells boxTurtle to move forward, reassigns 2 to drawn, and tells boxTurtle to turn facing west.

  9. Lines 12–16: The condition drawn < 4 still holds. The computer tells boxTurtle to move forward, reassigns 3 to drawn, and tells boxTurtle to turn facing north.

  10. Lines 12–16: The condition drawn < 4 still holds. The computer tells boxTurtle to move forward, reassigns 4 to drawn, and tells boxTurtle to turn facing east.

  11. Line 12: The condition drawn < 4 is finally false. So the computer is done with the while loop and now proceeds to the first statement following the loop's body, line 17.

  12. Line 17: The computer tells boxTurtle to hide itself.

One subtlety of while loops is that the computer checks the condition only when it reaches the end of the loop's body. In the last iteration of the while loop of this example, after drawn is assigned the value 4 in line 14, the turtle nonetheless turns to face east in line 15, because the computer must complete the body of the while loop before checking the condition again.

A detail to remember

Notice that a while loop involves no semicolons! Beginners are often tempted to add one anyway, after the parentheses.

while(drawn < 4); {   // Wrong! The semicolon messes up this code.
    drawn = drawn + 1;
}

Irritatingly, the Java compiler will accept this with a very different meaning than intended: It will understand the body of the loop to be an empty statement terminated by the semicolon before the opening brace, and the part in braces will be something to be done only once the loop completes. But the loop will never complete, because the computer will end up repeatedly checking whether drawn < 4 and then doing nothing.

5.2. Conditions

Alongside int and double among the primitive types is the boolean type, which is used to represent whether some fact holds. There are only two valid boolean values: true and false. (And if you ever want to refer to these constant boolean values in a program, that's exactly how you write them: true or false.)

Aside

Why call this type boolean? It's named after a 19th-century mathematician named George Boole. Boole was the first to notice that and and or, two common ways to combine true/false values, had some marked similarity to multiplication and addition of integers. This observation led to a sort of arithmetic of true/false values that came to be called Boolean algebra.

When Boole noticed this, people scoffed at Boole's work as being a rather pointless game. But it turned out to form the foundation of designing digital circuits.

The most common usage of the boolean type is implicit: When you compare two numerical values (as done using the `<' operator on line 12 of Figure 5.2), the comparison operator takes two numeric values and computes a boolean value. Java has several comparison operators, all of which operate on two numerical values and result in a boolean value.

<less than
<=less than or equal
>greater than
>=greater than or equal
==equal
!=not equal

When the computer reaches a while loop as on line 12 of Figure 5.2, it evaluates the expression in the parentheses. Because the expression must compute a boolean value, the result will be either true or false, and the computer will use this result to determine whether to go through the body of the loop.

A detail to remember

Notice the doubled equal sign (==) for testing equality! In Java, the single equal sign (=) represents assignment, as we've seen in our assignment statements. Beginners often find this somewhat confusing, but eventually the distinction is easy: Use == when you want to see whether two existing values are equal (without changing anything), and = when you want to change the value of a variable. You'll almost never see a single equal sign inside a while loop.

A detail to remember

One occassional pitfall when comparing doubles is that round-off errors can cause unexpected results. For example, 1.2 - 1.1 turns out to be 0.09999999999999985, which is different from 0.1. So if we evaluated 1.2 - 1.1 == 0.1, the value would unexpectedly turn out to be false. To avoid errors, when you are testing to see if two doubles are equal, you should instead test to see if the absolute value of their difference is small.

Sometimes you will want to combine conditions together to create a more complex condition. Java incorporates other operators to permit this.

&& and (true if both sides hold)
|| or (true if either side holds, or if both hold)
! not (true if expression doesn't hold)

For example, to see whether n refers to a value between 1 and 10, we would want to see if n is at least 1 and at most 10. We can do this using the && operator: n >= 1 && n <= 10. (Java would not allow 1 <= n <= 10.)

Here are some other examples.

!(n >= 1 && n <= 10) true if n is not between 1 and 10
n < 1 || n > 10 true if n is less than 1 or greater than 10

In fact, these operators fall into the same precedence hierarchy as all the other types we have seen so far. Here's all of the operators we have seen so far listed in order of precedence. (Technically, the assignment symbol is also an operator, which would appear at the very bottom level below, but it's better not to think of it as an operator.)

! - (unary operators)
* / %
+ -
< <= > >=
== !=
&&
||

The highest level is reserved for unary operators, which are operators that operate on only a single value, including the not operator ! and the negation operator -. The minus sign can be used both as a unary operator (in which case it represents negation, as in abs = -x;) and as a binary operator (in which case it represents subtraction, as in diff = y - x;).

5.3. Incrementing assignments

You'll find that, in the context of loops, it's quite frequent that you write a statement like line 14 of DrawSquareLoop.

drawn = drawn + 1;

This reassigns drawn to one more than it was before. This operation is so common that Java has a way of abbreviating it, to save you the bother of having to type the variable name twice.

drawn++;

Similarly, Java also has an abbreviation for decrementing: i--; is equivalent to i = i - 1;.

A detail to remember

Beginners sometimes have difficulty distinguishing between drawn++ and drawn + 1. These two fragments are not at all synonymous. The first — drawn++ — changes the value of the variable drawn. By contrast, drawn + 1 does not have any effect on drawn: It computes the number that is one more than drawn, but drawn does not change.

For those cases when you want to add something other than 1 to a variable, Java has another shortcut, the += operator.

drawn += 10;

This line would be equivalent to drawn = drawn + 10;. You can analogously use -=, *=, /=, and %=.

Exercise 5.1

For each of the following conditions, describe the variable values for which the condition is true.

a.x * x == x && x > -1
b.score > 90 || (bonus && score == 89)
c.!(k == 1)

Exercise 5.2

Write a condition to test whether an int variable year represents a leap year. (Remember that a year is a leap year if it is a multiple of 4, except for years that are multiples of 100 but not 400. For example, 1992 and 2000 are leap years; 2100 is not.)

Exercise 5.3

Without running the program on a computer, draw a picture of what the WhileMystery program of Figure 5.3 would draw on the screen.

Figure 5.3: The WhileMystery class.

  1  import turtles.*;
  2  
  3  public class WhileMystery extends TurtleProgram {
  4      public void run() {
  5          Turtle crush = new Turtle(100, 100);
  6          int len = 10;
  7          while(len < 200) {
  8              crush.forward(len);
  9              crush.left(90);
 10              crush.forward(len);
 11              crush.left(90);
 12              len += 10;
 13          }
 14          crush.hide();
 15      }
 16  }

Exercise 5.4

Modify the DrawSquareLoop program of Figure 5.2 so that it insists the user types a number between 5 and 195: As long as the user types a number outside this range, the compiler should ask again and again.

Exercise 5.5

Modify the DrawSquareLoop program of Figure 5.2 so that it draws an octagon in the center of the window. It should read a single number from the user, configuring the length of each side of the octagon to be drawn. If s represents each side's length, then the left vertex of the centered octagon's top horizontal edge would be at (100 − 0.5 s, 100 − 1.207 s).