Skip to main content

Repeating with while

A while loop runs its block again and again for as long as its test holds. Trace one pass by pass, halve 13 down to 0 to rebuild its binary form 1101, and learn the start, test and update every loop needs, the loop that never ends and the count that is off by one.
P01.3.2L0 Foundation25 minIn review

Before this lesson

P01.3.1 Choosing a path: if, elif and else P01.2.3 Arithmetic and expressions P01.1.4 Bits, bytes and memory

After this lesson you can

  • Trace a while loop pass by pass in a trace table, recording the test and the names after each pass.
  • Name the three parts every loop needs (a start, a test and an update) and find the missing or wrong part of a loop that never ends.
  • Convert a whole number to binary by halving it in a while loop, explain why the remainders are its digits, and check the result with bin.
  • Count exactly how many times a loop body runs and its test is made, and fix a loop that is off by one.

In review. The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.

The question

In P01.1.4 you found that 13 is 1101 in binary. One way to get there is to halve 13, keep the remainder, and go on halving until nothing is left. Thirteen needs four halvings; 100 needs seven; a million needs twenty. How does a program repeat a step when nobody knows in advance how many times it will be needed?

From the last lesson

1. With the tests score >= 70 and then score >= 50, what band does a score of 70 get, and why?

Show answer

Distinction. \({70 \ge 70}\) is True, and the first True test wins.

2. Which of 0, '0', '' and None count as false in a condition?

Show answer

0, '' and None. The string '0' has one character in it, so it counts as true.

Intuition

An if tests once and runs its block at most once. A while loop tests, runs its block if the test is True, and then goes back and tests again. It repeats for as long as the test stays True, and the first time the test is False, control leaves the loop and carries on with the line after it. One run of the block is called a pass, and the block is the loop’s body.

A flow chart. Start leads to n = 13, then digits = '', then a diamond n > 0. Its True exit, labelled True: run the body, goes down to the two body boxes digits = str(n % 2) + digits and n = n // 2, which a bracket marks as the body, one pass. From the second body box a green arrow runs left, up the left-hand side, labelled back to the test, and into the diamond again. The diamond's False exit goes right to print(digits) and then to End. A note reads: for n = 13 the body runs 4 times and the test is made 5 times.
P01.3.2-F1

A while loop as a flow chart: the arrow that goes back is what makes it a loop. The test is made before every pass, and once more at the end, when it is False.

The picture is the flow chart of an if with one extra arrow, the one that goes back up. Everything about loops follows from it: the body can run many times, or once, or not at all, and the loop ends only when something in the body has made the test False.

Build it up

Step 1. One halving by hand. P01.2.3 gave two operators for division in whole numbers: \({13 \mathbin{//} 2}\) is 6, the whole number of halves, and \({13 \mathbin{\%} 2}\) is 1, the remainder. So 13 is 6 twos and 1 left over.

Step 2. Repeat until nothing is left. Halve 6: 3, remainder 0. Halve 3: 1, remainder 1. Halve 1: 0, remainder 1. Now the number is 0 and there is nothing more to halve, so we stop. That was four halvings, and the remainders, in the order they appeared, were 1, 0, 1, 1.

Step 3. Read the remainders upwards. Written from the last one to the first, the remainders are 1101, the binary form of 13: \({8 + 4 + 0 + 1 = 13}\). The first remainder is the 1s digit and the last one is the 8s digit.

Left, titled halve, and keep the remainder: a column of blue boxes 13, 6, 3, 1, 0 joined by green arrows labelled // 2. Beside each of the first four boxes the remainder is worked out: 13 % 2 = 1, the 1s digit; 6 % 2 = 0, the 2s digit; 3 % 2 = 1, the 4s digit; 1 % 2 = 1, the 8s digit. Beside the 0 it says n is 0: stop. A green arrow pointing up is labelled read upwards. Right, titled 13 in binary: place values 8, 4, 2, 1 above four blue boxes holding 1, 1, 0, 1, then 8 + 4 + 0 + 1 = 13, and bin(13) gives '0b1101'.
P01.3.2-F2

Halving 13 down to 0. Each remainder is one binary digit; read upwards, they spell 1101.

Step 4. Say it in Python. Each halving does the same two things: put the new remainder in front of the digits found so far, and halve the number. That is the body. We go on while the number is greater than 0. That is the test.

n = 13
digits = ''
while n > 0:
    digits = str(n % 2) + digits
    n = n // 2
print(digits)

str turns the remainder into text, and + joins two pieces of text (P01.2.1), so the newest digit lands at the front.

The formal statement

NoteThe while statement
while condition:
    body

Python evaluates the condition. If it is true, it runs the body and then evaluates the condition again. This repeats until the condition is false, which may happen the first time; then the loop ends and the line after the body runs next.

Counting passes. Each pass is preceded by a test that came out True, and the loop ends with one test that came out False. So if the body runs \(k\) times, the test is made \({k + 1}\) times. For 13 the body runs 4 times and the test is made 5 times. A body can also run 0 times: start with n = 0 and the very first test is False.

The three parts of a loop. A loop that is meant to end needs three things:

  • a start: the names the test reads get their first values before the loop (n = 13);
  • a test that decides whether another pass is needed (n > 0);
  • an update in the body that moves things towards the test being False (n = n // 2).

Why the halving loop ends. The body runs only when \({n > 0}\). For such a whole number, \({n \mathbin{//} 2}\) is at most half of \(n\), and half of a positive number is smaller than the number. So every pass makes \(n\) smaller, and it stays a whole number that is at least 0. A whole number cannot keep getting smaller for ever without going below 0, so after some pass \(n\) is 0 and the test is False.

Why the remainders are the binary digits. P01.2.3 tied the two operators together by \(a = {(a \mathbin{//} b) \times b} + {a \mathbin{\%} b}\). With \({b = 2}\), the four halvings of 13 read

\[ \begin{aligned} 13 &= 2 \times 6 + 1 \\ 6 &= 2 \times 3 + 0 \\ 3 &= 2 \times 1 + 1 \\ 1 &= 2 \times 0 + 1 . \end{aligned} \]

Put each line into the one above it, one at a time:

\[ \begin{aligned} 13 &= 2 \times 6 + 1 \\ &= 2 \times (2 \times 3 + 0) + 1 \\ &= 4 \times 3 + 2 \times 0 + 1 \\ &= 4 \times (2 \times 1 + 1) + 2 \times 0 + 1 \\ &= 8 \times 1 + 4 \times 1 + 2 \times 0 + 1 \times 1 . \end{aligned} \]

In the last line, the 1 in \({8 \times 1}\) is the quotient of the third halving, and the fourth line says it is \({2 \times 0 + 1}\): it is the fourth remainder, with 0 left to halve. So the last line is the place-value form of 1101: one 8, one 4, no 2 and one 1. The first remainder is the 1s digit and each later remainder belongs one place further left, which is why the loop puts each new digit in front.

The same equation, \(n = {2 \times (n \mathbin{//} 2)} + {n \mathbin{\%} 2}\), says that the binary digits of \(n\) are those of \({n \mathbin{//} 2}\) with one more digit, the remainder, written after them. So each halving drops the last binary digit, and the loop makes exactly one pass for each binary digit of the number it starts with: 4 for 13, and 7 for 100, which is 1100100.

Worked example

Trace the halving loop for 13, one row per pass. Before the loop, line 1 binds n to 13 and line 2 binds digits to the empty string. Then:

  • Pass 1: the test \({13 > 0}\) is True. \({13 \mathbin{\%} 2 = 1}\), so digits becomes '1'; \({13 \mathbin{//} 2 = 6}\), so n becomes 6.
  • Pass 2: \({6 > 0}\) is True. The remainder is 0, so digits becomes '01'; n becomes 3.
  • Pass 3: \({3 > 0}\) is True. The remainder is 1, so digits becomes '101'; n becomes 1.
  • Pass 4: \({1 > 0}\) is True. The remainder is 1, so digits becomes '1101'; n becomes 0.
  • The test \({0 > 0}\) is False, so the loop ends and line 6 prints 1101.
A trace table with the columns pass, n > 0, n % 2, digits and n. Row start, before the loop: digits '' and n 13. Pass 1: True, 1, '1', 6. Pass 2: True, 0, '01', 3. Pass 3: True, 1, '101', 1. Pass 4: True, 1, '1101', 0. Last row, test: False, highlighted yellow, with digits '1101' and n 0, marked leave the loop. Below: the body ran 4 times and the test was made 5 times; print(digits) shows 1101.
P01.3.2-F3

The trace table of the halving loop. Each row shows the test, the remainder and the names after the pass; the yellow False is the test that ends the loop.

Counted line by line, the program ran 16 lines: lines 1 and 2 once, the test on line 3 five times, lines 4 and 5 four times each, and line 6 once. The body ran 4 times and the test 5 times, as the counting rule says.

Code

The loop from the build-up, then two checks: bin gives Python’s own binary form of a number, and int with a second argument of 2 reads binary text back into a number (both met in P01.1.4).

n = 13
digits = ''
while n > 0:
    digits = str(n % 2) + digits
    n = n // 2
print(digits)
print(bin(13))
print(int(digits, 2))
1101
0b1101
13

The 0b at the front of bin’s answer only marks the text as binary. Now count the passes with a second name that the body increases by one, for a bigger number:

n = 100
digits = ''
passes = 0
while n > 0:
    digits = str(n % 2) + digits
    n = n // 2
    passes = passes + 1
print(digits, passes)
1100100 7

Seven passes for 100, one for each of its seven binary digits. This repeat-until-done shape is the skeleton of every training loop: a model’s parameters get one small update per pass, and the loop stops when the loss has stopped falling or a budget of passes is used up (ML01.5).

Explore

This module’s interactive, the flow-chart tracer, lives in lesson P01.3.3. Its second program is this lesson’s halving loop. Set n with the slider and step through: the test lights up before every pass, and a counter shows how many times the body has run. Try 64, then 63, then 0.

Pitfalls

Two number lines from minus 6 to 14, each with the code n = 13, then a while header, then n = n - 2. Top, marked with a cross and titled while n != 0: never ends: green hops of 2 go left from 13 through 11, 9, 7, 5, 3 and 1; the hop from 1 lands on minus 1, drawn in reddish purple, with the note 1 − 2 is −1: 0 is jumped over, and the hops carry on past minus 5 with a dashed arrow. Bottom, marked with a tick and titled while n > 0: ends after 7 passes: the same hops from 13 down to minus 1, where a larger dot is marked −1 > 0 is False: stop.
P01.3.2-F4

Wrong beside right. Counting down by 2 from 13 never lands on 0, so a test of n != 0 never becomes False. A test of n > 0 stops after 7 passes, at \(-1\).

“The loop will stop by itself.”

Only if the body changes what the test reads. Leave out the update and the halving loop never ends:

n = 13
digits = ''
while n > 0:
    digits = str(n % 2) + digits

n stays 13, so \({13 > 0}\) is True for ever. A program stuck like this is stopped from the keyboard by pressing Ctrl+C, and Python reports a KeyboardInterrupt. When a loop does not end, look first for its start, its test and its update.

“Testing != is as good as testing >.”

Only if the update is sure to land exactly on the stop value. Counting down by 2 from 13 visits only odd numbers, so it jumps from 1 to \(-1\) and never equals 0. A test such as n > 0 stops as soon as the value has gone past the line, wherever it lands.

“My loop prints 1 to 5.”

Count the passes. This loop runs its body once for each value of count that passes the test, and 5 does not pass count < 5:

count = 1
while count < 5:
    print(count)
    count = count + 1
1
2
3
4

It prints four lines, 1 to 4: a loop that is off by one. Test count <= 5 instead, or start at 0 and print count + 1. Before you trust a loop, check its first pass and its last.

“A loop always runs its body at least once.”

A while loop tests first. With n = 0 the halving loop’s first test is False, the body never runs, and digits stays the empty string, so the program prints an empty line, although bin(0) is '0b0'. Exercise 2 repairs it.

Check yourself

Recall

1. When does a while loop stop?

Show answer

When its test is False at the moment it is made, at the top of a pass. The loop then ends and the line after its body runs.

2. Name the start, the test and the update of the halving loop.

Show answer

Start: n = 13 (and digits = ''). Test: n > 0. Update: n = n // 2.

3. A loop’s body ran 4 times. How many times was its test made?

Show answer

5 times: once before each of the 4 passes, and once more when it came out False.

4. What does the halving loop print when n starts at 6?

Show answer

110. The remainders are 0, 1 and 1, and read upwards they give 110, which is \({4 + 2 = 6}\).

5. Why does while n != 0: with the update n = n - 2 never end when n starts at 13?

Show answer

Subtracting 2 from an odd number gives an odd number, so n goes 13, 11, …, 1, \(-1\), and never equals 0. The test n != 0 is True for ever.

Exercises

1. ★ Trace the halving loop for n = 6 in a trace table with one row per pass, and check your answer with bin(6).

Show solution

Start: digits is '', n is 6. Pass 1: \({6 > 0}\) is True, the remainder is 0, digits is '0', n is 3. Pass 2: \({3 > 0}\) is True, the remainder is 1, digits is '10', n is 1. Pass 3: \({1 > 0}\) is True, the remainder is 1, digits is '110', n is 0. The test \({0 > 0}\) is False, so the loop ends after 3 passes and 4 tests. bin(6) is '0b110', which agrees.

2. ★★ What does the halving program print when n starts at 0, and why? Add an if statement after the loop so that it prints 0 in that case and nothing changes for any other number.

Show solution

It prints an empty line. The first test, \({0 > 0}\), is False, so the body never runs and digits keeps its start value ''. After the loop add

if digits == '':
    digits = '0'

For any start value above 0 the body runs at least once, so digits is not empty and the new block is skipped.

3. ★★★ For which starting values does the halving loop make exactly 7 passes? Explain your answer with binary digits.

Show solution

The loop makes one pass for each binary digit of its starting value, because halving drops the last digit and the loop stops when no digits are left. So the answer is every number with exactly 7 binary digits. The smallest is 1000000, which is \({2^6 = 64}\), and the largest is 1111111, which is \(64 + 32 + 16 + 8 + 4 + 2 + 1 = 127\). Every number from 64 to 127 makes 7 passes; 63 makes 6 and 128 makes 8.

Summary card

A while loop repeats its body for as long as its test stays True.

The anchor figure again: the flow chart of the halving loop, with the diamond n > 0, its True exit down into the body digits = str(n % 2) + digits and n = n // 2, the green arrow back up to the diamond, and the False exit to print(digits) and End.
P01.3.2-F1

The arrow back to the test makes a loop.

  • Rule. Test; if True, run the body and test again; if False, leave the loop.
  • Counting. A body that runs \(k\) times has its test made \({k + 1}\) times, and \(k\) can be 0.
  • Three parts. A start before the loop, a test, and an update in the body that moves towards the test being False.
  • Halving. n % 2 and n // 2 in a loop give the binary digits, last one first; bin checks them.

Sources and next steps

Sources. Each was opened and checked against this lesson on 12 November 2026.

  • Python Software Foundation, The Python Tutorial, section 3.2, First Steps Towards Programming. The while loop executes as long as its condition remains true; the body of the loop is indented, and every line of a block must be indented by the same amount.
  • Python Software Foundation, The Python Language Reference, section 8.2, The while statement. The statement repeatedly tests the expression and runs the suite while it is true; the test may be false the first time it is made.
  • Ana Bell, MIT OpenCourseWare 6.100L, Fall 2022 (CC BY-NC-SA 4.0). Lecture 3 slides: slide 8 (check the condition again, repeat until it is False, loop for ever if it never is), slide 12 (stop a runaway loop with Ctrl-C), and slides 16 and 17, whose loops give the loop variable its first value before the loop, test it in the condition and change it inside the body. Lecture 4 slides: slides 43 and 44 convert a whole number to binary with x % 2 for the last bit and x // 2 in a while loop.
  • Python Software Foundation, Python built-ins reference, Built-in functions: bin. Converts an integer to a binary string that starts with 0b.

Next. P01.3.3 Repeating with for and range meets a loop that does the start, the test and the update for you, by visiting the items of a sequence one at a time.

This lesson unlocks

P01.3.3 Repeating with for and range

Your progress is saved in this browser only. No account, no tracking.
Back to top