Previous Up Next

Buy this book at Amazon.com

This HTML version of the book is provided as a convenience, but some math equations are not translated correctly. The PDF version is more reliable.

Chapter 4  Loops

4.1  Updating variables

In Exercise 3, you might have been tempted to write something like

a = a - 0.05*a + 0.03*b
b = b + 0.05*a - 0.03*b

But that would be wrong, so very wrong. Why? The problem is that the first line changes the value of a, so when the second line runs, it gets the old value of b and the new value of a. As a result, the change in a is not always the same as the change in b, which violates the principle of Conversation of Cars!

One solution is to use temporary variables anew and bnew:

anew = a - 0.05*a + 0.03*b
bnew = b + 0.05*a - 0.03*b
a = anew
b = bnew

This has the effect of updating the variables “simultaneously;” that is, it reads both old values before writing either new value.

The following is an alternative solution that has the added advantage of simplifying the computation:

atob = 0.05*a - 0.03*b
a = a - atob
b = b + atob

It is easy to look at this code and confirm that it obeys Conversation of Cars. Even if the value of atob is wrong, at least the total number of cars is right. And that brings us to the Seventh Theorem of Debugging:

The best way to avoid a bug is to make it impossible.

In this case, removing redundancy also eliminates the opportunity for a bug.

4.2  Kinds of error

There are four kinds of error:

Syntax error:
You have written a MATLAB command that cannot execute because it violates one of the rules of syntax. For example, you can’t have two operands in a row without an operator, so pi r^2 contains a syntax error. When MATLAB finds a syntax error, it prints an error message and stops running your program.
Runtime error:
Your program starts running, but something goes wrong along the way. For example, if you try to access a variable that doesn’t exist, that’s a runtime error. When MATLAB detects the problem, it prints an error message and stops.
Logical error:
Your program runs without generating any error messages, but it doesn’t do the right thing. The problem in the previous section, where we changed the value of a before reading the old value, is a logical error.
Numerical error:
Most computations in MATLAB are only approximately right. Most of the time the errors are small enough that we don’t care, but in some cases the roundoff errors are a problem.

Syntax errors are usually the easiest. Sometimes the error messages are confusing, but MATLAB can usually tell you where the error is, at least roughly.

Runtime errors are harder because, as I mentioned before, MATLAB can tell you where it detected the problem, but not what caused it.

Logical errors are hard because MATLAB can’t help at all. Only you know what the program is supposed to do, so only you can check it. From MATLAB’s point of view, there’s nothing wrong with the program; the bug is in your head!

Numerical errors can be tricky because it’s not clear whether the problem is your fault. For most simple computations, MATLAB produces the floating-point value that is closest to the exact solution, which means that the first 15 significant digits should be correct. But some computations are ill-conditioned, which means that even if your program is correct, the roundoff errors accumulate and the number of correct digits can be smaller. Sometimes MATLAB can warn you that this is happening, but not always! Precision (the number of digits in the answer) does not imply accuracy (the number of digits that are right).

4.3  Absolute and relative error

There are two ways of thinking about numerical errors, called absolute and relative.

Absolute error:
It is just the difference between the correct value and the approximation. We usually write the magnitude of the error, ignoring its sign, because it doesn’t matter whether the approximation is too high or too low.
Relative error:
It is the error expressed as a fraction (or percentage) of the exact value.

For example, we might want to estimate 9! using the formula √18 π ( 9 / e)9. The exact answer is 9 · 8 · 7 · 6 · 5 · 4 · 3 · 2 · 1 = 362,880. The approximation is 359,536.87. The absolute error is 3,343.13.

At first glance, that sounds like a lot—we’re off by three thousand—but it is worth taking into account the size of the thing we are estimating. For example, $3000 matters a lot if we are talking about my annual salary, but not at all if we are talking about the national debt.

A natural way to handle this problem is to use relative error. In this case, we would divide the error by 362,880, yielding .00921, which is just less than 1%. For many purposes, being off by 1% is good enough.

4.4  for loops

A loop is a part of a program that executes repeatedly; a for loop is the kind of loop that uses the for statement.

The simplest use of a for loop is to execute one or more lines a fixed number of times. For example, in the last chapter we wrote a script named car_update that simulates one week in the life of a rental car company. To simulate an entire year, we have to run it 52 times:

for i=1:52
    car_update
end

The first line looks like an assignment statement, and it is like an assignment statement, except that it runs more than once. The first time it runs, it creates the variable i and assigns it the value 1. The second time, i gets the value 2, and so on, up to 52.

The colon operator, :, specifies a range of integers. In the spirit of unit testing, you can create a range at the prompt:

>> 1:5
ans =  1     2     3     4     5

The variable you use in the for statement is called the loop variable. It is a common convention to use the names i, j, and k as loop variables.

The statements inside the loop are called the body. By convention, they are indented to show that they are inside the loop, but the indentation does not actually affect the execution of the program. The end of the loop is officially marked by the end statement.

To see the loop in action you can run a loop that displays the loop variable:

>> for i=1:5
    i
end

i = 1
i = 2
i = 3
i = 4
i = 5

As this example shows, you can run a for loop from the command line, but it’s much more common to put it in a script.

Exercise 1   Create a script named car_loop that uses a for loop to run car_update 52 times. Remember that before you run car_update, you have to assign values to a and b. For this exercise, start with the values a = 150 and b = 150.

If everything goes smoothly, your script will display a long stream of numbers on the screen. But it is probably too long to fit, and even if it fit, it would be hard to interpret. A graph would be much better!

4.5  plotting

plot is a versatile function for plotting points and lines on a two-dimensional graph. Unfortunately, it is so versatile that it can be hard to use (and hard to read the documentation!). We will start simple and work our way up.

To plot a single point, type

>> plot(1, 2)

A Figure Window should appear with a graph and a single, blue dot at x position 1 and y position 2. To make the dot more visible, you can specify a different shape:

>> plot(1, 2, 'o')

The letter in single quotes is a string that specifies how the point should be plotted. You can also specify the color:

>> plot(1, 2, 'ro')

r stands for red; the other colors include green, blue, cyan, magenta, yellow, and black. Other shapes include +, *, x, s (for square), d (for diamond), and ^ (for a triangle).

When you use plot this way, it can only plot one point at a time. If you run plot again, it clears the figure before making the new plot. The hold command lets you override that behavior. hold on tells MATLAB not to clear the figure when it makes a new plot; hold off returns to the default behavior.

Try this:

>> hold on
>> plot(1, 1, 'o')
>> plot(2, 2, 'o')
>> hold off

You should see a figure with three circles. MATLAB scales the plot automatically so that the axes run from the lowest value in the plot to the highest. So in this example the points are plotted in the corners.

Exercise 2   Modify car_loop so that each time through the loop it plots the value of a versus the value of i.

Once you get that working, modify it so it plots the values of a with red circles and the values of b with blue diamonds.

One more thing: if you use hold on to prevent MATLAB from clearing the figure, you might want to clear the figure yourself, from time to time, with the command clf.

4.6  Sequences

In mathematics a sequence is a set of numbers that corresponds to the positive integers. The numbers in the sequence are called elements. In math notation, the elements are denoted with subscripts, so the first element of the series A is A1, followed by A2, and so on.

for loops are a natural way to compute the elements of a sequence. As an example, in a geometric sequence, each element is a constant multiple of the previous element. As a more specific example, let’s look at the sequence with A1 = 1 and the ratio Ai+1 = Ai/2, for all i. In other words, each element is half as big as the one before it.

The following loop computes the first 10 elements of A:

a = 1
for i=2:10
    a = a/2
end

Each time through the loop, we find the next value of a by dividing the previous value by 2. Notice that the loop range starts at 2 because the initial value of a corresponds to A1, so the first time through the loop we are computing A2.

Each time through the loop, we replace the previous element with the next, so at the end, a contains the 10th element. The other elements are displayed on the screen, but they are not saved in a variable. Later, we will see how to save all of the elements of a sequence in a vector.

This loop computes the sequence recurrently, which means that each element depends on the previous one. For this sequence it is also possible to compute the ith element directly, as a function of i, without using the previous element. In math notation, Ai = A1 ri−1.

Exercise 3   Write a script named sequence that uses a loop to compute elements of A directly.

4.7  Series

In mathematics, a series is the sum of the elements of a sequence. It’s a terrible name, because in common English, “sequence” and “series” mean pretty much the same thing, but in math, a sequence is a set of numbers, and a series is an expression (a sum) that has a single value. In math notation, a series is often written using the summation symbol ∑.

For example, the sum of the first 10 elements of A is

10
i=1
 Ai     (1)

A for loop is a natural way to compute the value of this series:

A1 = 1;
total = 0;
for i=1:10
    a = A1 * 0.5^(i-1);
    total = total + a;
end
ans = total

A1 is the first element of the sequence, so each time through the loop a is the ith element.

The way we are using total is sometimes called an accumulator; that is, a variable that accumulates a result a little bit at a time. Before the loop we initialize it to 0. Each time through the loop we add in the ith element. At the end of the loop total contains the sum of the elements. Since that’s the value we were looking for, we assign it to ans.

Exercise 4   This example computes the terms of the series directly; as an exercise, write a script named recurrent_series that computes the same sum by computing the elements recurrently. You will have to be careful about where you start and stop the loop.

4.8  Generalization

As written, the previous example always adds up the first 10 elements of the sequence, but we might be curious to know what happens to total as we increase the number of terms in the series. If you have studied geometric series, you might know that this series converges on 2; that is, as the number of terms goes to infinity, the sum approaches 2 asymptotically.

To see if that’s true for our program, we could replace the constant, 10, with a variable named n:

A1 = 1;
total = 0;
for i=1:n
    a = A1 * 0.5^(i-1);
    total = total + a;
end
ans = total

The code above can now compute any number of terms, with the precondition that you have to set n before you execute the code. Put the code in a file named series.m, then run the script with different values of n as shown in the following:

>> n=10; series

total = 1.99804687500000

>> n=20; series

total = 1.99999809265137

>> n=30; series

total = 1.99999999813735

>> n=40; series

total = 1.99999999999818

It sure looks like it’s converging on 2.

Replacing a constant with a variable is called generalization. Instead of computing a fixed, specific number of terms, the new script is more general; it can compute any number of terms.

This is an important idea we will come back to when we talk about functions.

4.9  Glossary

absolute error:
The difference between an approximation and an exact answer.
relative error:
The difference between an approximation and an exact answer, expressed as a fraction or percentage of the exact answer.
loop:
A part of a program that runs repeatedly.
loop variable:
A variable, defined in a for statement, that gets assigned a different value each time through the loop.
range:
The set of values assigned to the loop variable, often specified with the colon operator; for example 1:5.
body:
The statements inside the for loop that are run repeatedly.
sequence:
In mathematics, a set of numbers that correspond to the positive integers.
element:
A member of the set of numbers in a sequence.
recurrently:
A way of computing the next element of a sequence based on previous elements.
directly:
A way of computing an element in a sequence without using previous elements.
series:
The sum of the elements in a sequence.
accumulator:
A variable that is used to accumulate a result a little bit at a time.
generalization:
A way to make a program more versatile, for example by replacing a specific value with a variable that can have any value.

4.10  Exercises

Exercise 5  

We have already seen the Fibonacci sequence, F, which is defined recurrently as

for  i ≥ 3,     Fi = Fi−1 + Fi−2     (2)

In order to get started, you have to specify the first two elements, but once you have those, you can compute the rest. The most common Fibonacci sequence starts with F1 = 1 and F2 = 1.

Write a script called fibonacci2 that uses a for loop to compute the first 10 elements of this Fibonacci sequence. As a postcondition, your script should assign the 10th element to ans.

Now generalize your script so that it computes the nth element for any value of n, with the precondition that you have to set n before you run the script. To keep things simple for now, you can assume that n is greater than 0.

Hint: you will have to use two variables to keep track of the previous two elements of the sequence. You might want to call them prev1 and prev2. Initially, prev1 = F1 and prev2 = F2. At the end of the loop, you will have to update prev1 and prev2; think carefully about the order of the updates!

Exercise 6  

Write a script named fib_plot that loops i through a range from 1 to 20, uses fibonacci2 to compute Fibonacci numbers, and plots Fi for each i with a series of red circles.

Are you using one of our books in a class?

We'd like to know about it. Please consider filling out this short survey.


Think Bayes

Think Python 2e

Think Stats 2e

Think Complexity


Previous Up Next