1.6. Repeated Evaluation: While-Loops#

for-loops are ideal when you know the number of iterations in advance, like when computing a finite sum \(s_n = \sum_{i=1}^n \frac{1}{i}\).

However, sometimes the number of iterations isn’t known beforehand. For example, what if we needed to add terms to \(s_n\) until the next term becomes smaller than some tolerance \(\delta\)? For problems like this, a while-loop is the perfect tool.

The basic syntax is:

while condition
    # This code will repeat as long as the condition is true
end

1.6.1. Key Points#

  • If the condition is false initially, the loop body will never execute.

  • If the condition never becomes false, you will create an infinite loop.

  • You typically need to initialize a variable before the loop that is used in the condition, and then update that variable inside the loop.

Here is how we can solve the problem from above: compute \(s_n\), stopping when a term is smaller than \(\delta\).

function compute_s_delta(δ)
    s = 0.0
    term = 1.0
    i = 1
    
    while term  δ
        s += term
        i += 1
        term = 1 / i
    end
    
    return s
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.2. The break Statement#

Sometimes it is useful to exit a loop from somewhere in the middle of its body. The break statement allows you to do this immediately.

while condition
    # ... some code ...
    if termination_condition
        break
    end
    # ... more code ...
end

This pattern is very common. A popular technique is to create a deliberate infinite loop with while true and then use an if condition with break to control the exit.

1.6.3. The continue Statement#

The continue statement is similar to break, but instead of exiting the loop entirely, it immediately skips to the next iteration, bypassing any remaining code in the current iteration. This is useful for skipping certain steps under specific conditions.

1.6.4. Example: Square Root Calculation#

A classic way to compute square roots is with Newton’s method. To find \(\sqrt{a}\), we can iteratively improve an estimate \(x_n\) using the formula:

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

We start with an initial guess, like \(x_0 = 1.0\), and repeat until the change between successive estimates is smaller than some tolerance \(\varepsilon\). This is a perfect task for a while-loop, and we will explore two common ways to structure it.

1.6.4.1. Method 1: Using while true and an if statement#

One popular and readable pattern is to create an infinite loop with while true and then use an if statement to exit once the convergence criterion is met. This keeps the termination logic cleanly separated inside the loop body.

While break is often used to exit a loop, it’s even more direct to use return when the loop is inside a function. This immediately exits the entire function and sends back the final value, making the code more concise.

function my_sqrt_v1(a, ε = 1e-15) # Use a default value for the tolerance ε
    x = 1.0                     # Initial guess
    
    while true
        println("Current estimate: x = ", x)
        x_new = (x + a/x) / 2
        
        # Check for convergence and exit the loop if met
        if abs(x_new - x) < ε
            return x_new # Return the final, converged value
        end
        
        x = x_new
    end
end
my_sqrt_v1 (generic function with 2 methods)
my_sqrt_v1(256)
Current estimate: x = 1.0
Current estimate: x = 128.5
Current estimate: x = 65.24610894941634
Current estimate: x = 34.58485728656987
Current estimate: x = 20.993470372021676
Current estimate: x = 16.59386909154118
Current estimate: x = 16.010626831390027
Current estimate: x = 16.00000352670594
Current estimate: x = 16.00000000000039
Current estimate: x = 16.0
16.0

1.6.4.2. Method 2: Condition in the while Statement#

A more traditional approach is to place the termination logic directly in the while loop’s condition. This requires carefully initializing variables before the loop starts to ensure the condition can be evaluated correctly on the first pass.

function my_sqrt_v2(a, ε = 1e-15)
    x = 1.0
    x_new = (x + a/x) / 2 # Calculate the first step to initialize the change
    
    # Loop as long as the change is greater than or equal to the tolerance
    while abs(x_new - x)  ε
        println("Current estimate: x = ", x_new)
        x = x_new
        x_new = (x + a/x) / 2
    end
    
    return x_new
end
my_sqrt_v2 (generic function with 2 methods)
my_sqrt_v2(256)
Current estimate: x = 128.5
Current estimate: x = 65.24610894941634
Current estimate: x = 34.58485728656987
Current estimate: x = 20.993470372021676
Current estimate: x = 16.59386909154118
Current estimate: x = 16.010626831390027
Current estimate: x = 16.00000352670594
Current estimate: x = 16.00000000000039
Current estimate: x = 16.0
16.0