1.6. Repeated evaluation: while-loops#

We have seen above that for-loops are good for looping when you know the number of iterations, e.g to compute the finite sum \(s_n = \sum_{i=1}^n \frac{1}{i}\) for some given integer \(n\ge 1\). However, suppose the problem statement makes it difficult to predict the number of iterations. For example, if we had to compute the terms in \(s_n\) until a term is smaller than a given number \(\delta\).

For problems like this, when you don’t know the total number of iterations, you can use a while loop. It has the following syntax:

while #condition
    # Code repeated until the condition above becomes false
end

Note that:

  • The condition (#condition) might be false at the first time, which means the code inside the while loop will never be executed

  • The condition might never be false, which creates an infinite loop which never stops

  • You typically need some variable to determine the condition, which has to be initialized before the loop, and updated inside the loop

Here is an example of a code to solve the problem from above: compute \(s_n\), stopping when a term is smaller than \(\delta\):

function compute_s_delta(δ)
    sn = 0
    term = 1
    i = 1
    while term  δ
        sn += term
        i += 1
        term = 1 / i
    end
    sn
end
compute_s_delta (generic function with 1 method)
compute_s_delta(0.1)
2.9289682539682538
compute_s_delta(1e-8)
18.997896413852555

1.6.1. The break statement#

Sometimes it is convenient to determine somewhere inside the while loop that the loop should finish. This can be done with the break statement:

while #condition
    # Code 1 to be repeated...
    if #termination_condition
        break
    end
    # Code 2 to be repeated...
end

This will repeat like before, that is, until #condition becomes false. However, if #termination_condition becomes false, it will immediately finish the loop.

This way of writing while loops is common because you can check the condition anywhere in the loop (not just at the top). Another common usage of this is to set #condition to true, in which case the termination is completely controlled by #termination_condition.

1.6.2. The continue statement#

The continue statement is similar to the break statement, in that it can appear anywhere inside the loop. However, when a continue statement is encounted, the code will immediately go the next iteration and start at the beginning of the loop. This can be convenient to quickly skip an iteration without terminating the repetitions.

1.6.3. Example: Square-root#

A famous way for computing square-roots is to evaluate the following sequence (essentially Newton’s method for \(x^2=a\)):

\[ x_{n+1} = \frac12 \left( x_n + \frac{a}{x_n} \right) \]

for some initial guess \(x_0\), for example \(x_0 = 1\).

One way to decide when to terminate the iterations (and accept \(x_n\) as a good approximation to \(\sqrt{a}\)) is to loop as long as the last update \(|x_{n+1} - x_n|\) is greater than some tolerance \(\varepsilon\):

function my_sqrt(a, ε)
    x = 1    # Initial guess
    Δx = 1   # Need to initialize to get started
    while Δx  ε
        xnew = (x + a/x) / 2
        Δx = abs(xnew - x)
        x = xnew
        println("x = ", x)
    end
    x
end
my_sqrt (generic function with 1 method)
my_sqrt(256, 1e-15)
x = 128.5
x = 65.24610894941634
x = 34.58485728656987
x = 20.993470372021676
x = 16.59386909154118
x = 16.010626831390027
x = 16.00000352670594
x = 16.00000000000039
x = 16.0
x = 16.0
16.0