AP Computer Science A

Lesson 4: Loops — for, while, and Nested LoopsAP

🎧 Listen to this lesson

Unit 4 of the CED is iteration: while loops, for loops, nested loops, and the standard algorithms built from them. Iteration questions are the purest tracing tests on the exam — the code is short, the execution is long, and every point depends on tracking variables through many repetitions without slipping. This lesson builds the trace-table discipline and the handful of loop patterns that recur in almost every FRQ.

The while loop and the for loop

A while loop repeats its body as long as its condition is true, testing before each iteration — so the body may run zero times. A for loop packages the three control pieces in one header: initialisation, condition, update.

for (int i = 0; i < 5; i++)
{
    System.out.print(i + " ");
}
// prints: 0 1 2 3 4

The equivalent while version initialises before the loop, tests the same condition, and updates at the end of the body. The classic disasters are an update that never happens (infinite loop), and an off-by-one bound: i < 5 iterates 5 times (0–4); i <= 5 iterates 6 times (0–5). (Java also has a do-while loop, but it is deliberately not part of the AP subset — if you see one in the wild, know that it tests after the body; the exam will not use it.)

Trace tables: the only reliable method

Never trace a loop in your head. Draw columns for each variable and a row per iteration:

int n = 27;
int count = 0;
while (n > 1)
{
    n = n / 2;
    count++;
}
Checkn (before)Body runs?n (after)count
127yes131
213yes62
36yes33
43yes14
51no—4 (final)

Note the integer division shrinking n (27 → 13, not 13.5) — loop traces and Unit 1 arithmetic are always tested together. After the loop, count is 4 and n is 1.

Nested loops multiply

When a loop sits inside another, the inner loop completes a full run for each outer iteration, and the inner variable is re-initialised each time.

for (int row = 1; row <= 3; row++)
{
    for (int col = 1; col <= row; col++)
    {
        System.out.print("*");
    }
    System.out.println();
}
rowInner iterationsStars this rowTotal so far
1111
2223
3336

The output is a triangle of 6 stars. Nested-loop questions on the MCQ section are mostly counting questions: total body executions = product (or, as here, sum) of the iteration counts. Nested loops are also the engine of every 2D-array algorithm in Unit 8.

The standard loop algorithms

Almost every FRQ loop is one of these patterns in disguise:

  • Accumulator. Keep a running total outside the loop: sum += value; — initialise before, update inside, use after.
  • Counter with a condition. Increment only when a test passes: counting evens, vowels, values in a range.
  • Max/min. Initialise to the first candidate value, not to 0 — initialising a max-finder to 0 fails on all-negative data, and initialising a min-finder to 0 fails on all-positive data. Examiner reports flag this every year.
  • Digit processing. while (n > 0) { digit = n % 10; ...; n /= 10; } consumes a number digit by digit, right to left.
  • String traversal. Loop an index from 0 to s.length() - 1 and examine s.substring(i, i + 1) — the AP-safe way to walk a string one character at a time.
  • Early exit. return from inside a loop the moment the answer is known (searching); break leaves the loop but stays in the method. Know which one a question needs.

Real-world design: loops are where programs spend their time

Profilers consistently show that the overwhelming majority of execution time in real software is spent inside loops — a search box re-scanning results per keystroke, a game re-rendering 60 frames per second, a spreadsheet recalculating a column. That is why a loop that does slightly too much work (recomputing s.length() is fine in Java, but re-reading a file inside a loop is not) matters, and why the counting discipline in this lesson becomes the informal efficiency analysis the CED expects: how many times does the body run, as the input grows?

Key idea. Key idea: before writing any loop, state three things — what the loop variable starts at, exactly when the loop stops, and what is guaranteed true after each iteration. Most loop bugs are a failure of one of the three.

Common mistakes (from examiner reports)

  • Off-by-one bounds. < length versus <= length — with arrays the wrong one throws ArrayIndexOutOfBoundsException; with counters it silently adds an iteration.
  • Initialising max/min to 0. The most persistent FRQ error in this unit. Initialise from the data.
  • Modifying the loop variable inside the body as well as in the update — double increments skip values.
  • Semicolon after the header. for (int i = 0; i < 5; i++); compiles, loops over an empty body, and baffles its author. The exam includes this as a distractor.
  • Infinite loops from a non-shrinking condition. If the variable in the condition never changes toward the exit, the loop never ends — always identify the statement that makes progress.
  • Testing the wrong variable after the loop. After a search loop, the useful facts are the counter's final value and whether the loop exited early — not the loop variable's last assigned value inside.
Try it. Try it: how many times does the body of for (int i = 10; i > 0; i -= 3) run, and what is the last value printed by System.out.print(i + " ") inside it? (4 times: 10, 7, 4, 1.)

AP Exam Experience

Question 1. Consider the following code segment.

int sum = 0;
for (int i = 1; i <= 10; i += 3)
{
    sum += i;
}
System.out.println(sum);

What is printed?

  • (A) 19
  • (B) 22
  • (C) 25
  • (D) 30
  • (E) 55

Answer: (B). i takes the values 1, 4, 7, 10 (10 still satisfies <= 10), so sum is 1 + 4 + 7 + 10 = 22. (C) comes from including 13, which fails the condition.

Question 2. Consider the following code segment.

int n = 2048;
int digits = 0;
while (n > 0)
{
    digits++;
    n /= 10;
}
System.out.println(digits);

What is printed?

  • (A) 3
  • (B) 4
  • (C) 5
  • (D) 11
  • (E) Nothing; the loop never terminates.

Answer: (B). The loop strips one digit per iteration: 2048 → 204 → 20 → 2 → 0, four iterations. Note the edge case this pattern hides: if n started at 0, the loop would report 0 digits — handling that case is a classic FRQ scoring point.

Question 3. Consider the following code segment.

for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
    {
        System.out.print(i + j + " ");
    }
}

How many numbers are printed, and what is the last number printed?

  • (A) 6 numbers; last is 4
  • (B) 9 numbers; last is 4
  • (C) 9 numbers; last is 6
  • (D) 6 numbers; last is 6
  • (E) 3 numbers; last is 2

Answer: (B). The inner body runs 3 × 3 = 9 times. The final execution has i = 2 and j = 2, printing 4. (C) is the trap for adding the loop bounds (3 + 3) instead of the last variable values (2 + 2).

Free-Response Question. This question involves methods that analyse the digits of an integer. (a) Write the static method numDigits, which takes a non-negative int parameter and returns the number of digits it has. numDigits(7) returns 1, numDigits(2048) returns 4, and — watch the edge case — numDigits(0) returns 1. (b) Write the static method reverseNum, which takes a non-negative int parameter and returns the integer formed by reversing its digits. reverseNum(2048) returns 8402, and reverseNum(120) returns 21 (a leading zero in the reversal simply disappears).

Scoring guideline (9 points). Part (a) — 4 points:

  • +1 Correct method header: returns int, one int parameter
  • +1 Loops (or repeatedly divides) while reducing the parameter toward 0
  • +1 Counts one per division by 10
  • +1 Returns 1 when the parameter is 0 (edge case handled, e.g. by an initial check or a count starting at 1 for values < 10)

Part (b) — 5 points:

  • +1 Correct method header: returns int, one int parameter
  • +1 Extracts the last digit with % 10
  • +1 Removes the last digit with / 10 and repeats until the number is consumed
  • +1 Builds the reversed value multiplicatively (rev = rev * 10 + digit)
  • +1 Returns the reversed value; reverseNum(0) correctly returns 0

Model solution.

public static int numDigits(int n)
{
    if (n == 0)
    {
        return 1;
    }
    int count = 0;
    while (n > 0)
    {
        count++;
        n /= 10;
    }
    return count;
}

public static int reverseNum(int n)
{
    int rev = 0;
    while (n > 0)
    {
        rev = rev * 10 + n % 10;
        n /= 10;
    }
    return rev;
}


## Going deeper: a complete algorithm — counting factors
Watch the standard patterns from this lesson assemble into a real algorithm: count how many factors a positive integer `n` has.

int factors = 0; for (int d = 1; d <= n; d++) { if (n % d == 0) { factors++; } }

For `n = 12`, trace the tests: d = 1 ✓ (1), 2 ✓ (2), 3 ✓ (3), 4 ✓ (4), 5 ✗, 6 ✓ (5), 7–11 ✗, 12 ✓ (6). Result: 6 factors. Every pattern fires at once: the loop bound is **inclusive** (`<= n`) because `n` is its own factor — an off-by-one here silently answers 5; the condition uses `% == 0` (divisibility); the increment lives inside the condition (a counter with a test). The same skeleton, with the test replaced, counts divisors, digits with a property, array elements in a range, and characters in a class — which is why examiners return to it so often. A number with exactly 2 factors is prime, so `factors == 2` after this loop is a complete primality test for the values AP uses.

📊 Interactive

Interactive — hover or explore the chart above.

Keep reading to complete this lesson