Back to tutorial index

The 'for-loop' and vectorizaton


Topics in this lab

Introduction

In this lab, you will learn how to control the flow of execution of commands using a for loop.

Back to the top

The 'for' loop

Up until now, commands in a script have been executed in the order in which they appear in a script. We can control this order of execution using flow control statements. The for loop is a type of flow control statement that allows us to execute a set of commands multiple times. For example, in the following code fragment, the statement fprintf('Hello, World\n') gets executed 10 times, even though it only appears once in the code fragment.

for i = 1:10,
    fprintf('Hello, World!  This is iteration %d\n',i);
end
Hello, World!  This is iteration 1
Hello, World!  This is iteration 2
Hello, World!  This is iteration 3
Hello, World!  This is iteration 4
Hello, World!  This is iteration 5
Hello, World!  This is iteration 6
Hello, World!  This is iteration 7
Hello, World!  This is iteration 8
Hello, World!  This is iteration 9
Hello, World!  This is iteration 10

Back to the top

The anatomy of the 'for' loop

The for loop has three basic components : the enclosing keywords for and end which enclose the set of statements to be carried out multiple times by the loop (the statement fprintf('Hello, World\n'), in the above example), a loop index which is the variable that stores the current value of the loop counter (i in the above example), and an index array containing the range of values over which the loop index should vary (the array 1:10 in the above example). See below for the "Anatomy of a "for" loop"


Anatomy of a for loop


The number of times the loop executes the statements enclosed by the for and end is determined by the length of the array describing the loop range. Consider each of the following examples :

% Example 1
for i = 0:5:10,
    fprintf('Three brown bears; i = %2d\n',i);
end
Three brown bears; i =  0
Three brown bears; i =  5
Three brown bears; i = 10
% Example 2
for x = [3.1 5.6],
    fprintf('A couple of ducks; x = %4.1f\n',x);
end
A couple of ducks; x =  3.1
A couple of ducks; x =  5.6
% Example 3
for j = 10:-2:0,
    fprintf('Six Simple Simons sitting on a stump; j = %2d\n',j);
end
Six Simple Simons sitting on a stump; j = 10
Six Simple Simons sitting on a stump; j =  8
Six Simple Simons sitting on a stump; j =  6
Six Simple Simons sitting on a stump; j =  4
Six Simple Simons sitting on a stump; j =  2
Six Simple Simons sitting on a stump; j =  0
% Example 4
for j = 1:-1:10,
    fprintf('I am being ignored (:-((\n');
end

In each case, the statement enclosed by for loop was executed once for each entry in the loop index array. In the last example, the loop index array is empty, and so the enclosed statement did not get executed at all.

Back to the top

The 'for' loop - using the loop index variable

In most cases, the statements enclosed by the for loop will involve the value of the loop index variable. Each of the following loop examples illustrates how we can make use of the loop index variable.

clear all;
% Example 1 - Print out the value of the loop index
for i = 0:2:20,
    fprintf('i = %d\n',i);
end
i = 0
i = 2
i = 4
i = 6
i = 8
i = 10
i = 12
i = 14
i = 16
i = 18
i = 20
% Example 2 - Print out the entries in an array 'x', in reverse order.
x = rand(1,10);
for k = 10:-1:1,
    fprintf('x(%2d) = %8.4f\n',k, x(k));
end
x(10) =   0.4173
x( 9) =   0.2400
x( 8) =   0.1839
x( 7) =   0.1233
x( 6) =   0.2399
x( 5) =   0.0760
x( 4) =   0.4018
x( 3) =   0.5132
x( 2) =   0.3510
x( 1) =   0.6221

Example 3 - Fill in entries in an array 'y' and print each value

for j = 1:8,
    y(j) = sin(pi*(j-1)/2);
    fprintf('y(%d) = %16.8f\n',j,y(j));
end
y(1) =       0.00000000
y(2) =       1.00000000
y(3) =       0.00000000
y(4) =      -1.00000000
y(5) =      -0.00000000
y(6) =       1.00000000
y(7) =       0.00000000
y(8) =      -1.00000000
% Example 4 - Cumulative sums of the integers 1 through 10.
s = 0;
for k = 1:10,
    s = s + k;
    fprintf('Sum of the numbers 1 to %2d : %5d\n',k, s);
end
Sum of the numbers 1 to  1 :     1
Sum of the numbers 1 to  2 :     3
Sum of the numbers 1 to  3 :     6
Sum of the numbers 1 to  4 :    10
Sum of the numbers 1 to  5 :    15
Sum of the numbers 1 to  6 :    21
Sum of the numbers 1 to  7 :    28
Sum of the numbers 1 to  8 :    36
Sum of the numbers 1 to  9 :    45
Sum of the numbers 1 to 10 :    55

In all of the above examples, the loop index is an integer. This is by far the most common loop index array for the for loop. However, there is nothing in Matlab to prevent us from trying the following unusual (and not particularly recommended) ways to use the loop index.

% Example 5 - A confusing example in which 'x' is an array and 'y' takes on
% different values in the array 'x'.
x = linspace(-1,1,7);
for y = x,
    fprintf('y = %f\n',y);
end
y = -1.000000
y = -0.666667
y = -0.333333
y = 0.000000
y = 0.333333
y = 0.666667
y = 1.000000
% Example 6 - Let's see what we can do with strings.
for c = ['Hello', 'Goodbye','See Ya!'],
    fprintf('%s',c);
end
HelloGoodbyeSee Ya!

In the first case, the loop index array x is an array containing non-integer values, but the loop index y still takes on each value, and the print statement is executed the expected number of times, e.g. one time for each entry in x.

The second example is less familar, but only because we have not worked with strings much. Here, the loop in index is the array of characters

s = ['Hello', 'Goodbye','See Ya!']
s =
HelloGoodbyeSee Ya!

We can index into this array in exactly the same way as with numeric data. For example,

s(1:10)
ans =
HelloGoodb

We can also use the length function to get the length of s. This length tells us the number of times the statements in the for will be executed.

length(s)
ans =
    19

So in this case as well, the for loop above is behaving exactly as expected. Notice that we did not put a new line character into the fprintf statement in the the loop. If we had, our output for the odd 'string' loop would look like the following. We have added a loop counter here as well to see that the in fact, the number of times that the code inside the loop is called is equal to the length of the loop index array. In this case, the variable k acts like the loop index variable and is incremented by 1 each time the code in the loop is executed.

% add a new line character to the fprintf statement.
k = 1;
for c = ['Hello', 'Goodbye','See Ya!'],
    fprintf('%2d   %s\n',k,c);
    k = k + 1;
end
 1   H
 2   e
 3   l
 4   l
 5   o
 6   G
 7   o
 8   o
 9   d
10   b
11   y
12   e
13   S
14   e
15   e
16    
17   Y
18   a
19   !

A final, entertaining example involves the use of a "cell" array. We will not discuss cell arrays in detail now, but suppose you really wanted to loop over a list of words. The following syntax will allow you to do this:

for word = {'Howdy', 'Later', 'Cheerio'},
    fprintf('%s\n',word{:});
end
fprintf('The last word is ''%s''\n',word{:});
Howdy
Later
Cheerio
The last word is 'Cheerio'

As this example illustrates, the value of the loop index after we have completed the loop is the last value in the loop index array.

Back to the top

Rules for using the 'for' loop

Here are some basic principles to follow when using the for loop.

Rules and guidelines for the for loop.
  1. The for loop may enclose multiple Matlab statements,
  2. The number of times that enclosed statements get executed is equal to the length of the loop index array,
  3. The loop index variable may be used by the enclosed statements,
  4. One for loop may be nested inside of one another loop. Statements in the inner for loops may use the loop index variable from the outer loop.
  5. Loop index arrays most commonly contain integer values. Loop indices are often named i, j, k, m or n. Avoid the use of variable names x, y, z or w for loop indices.

Back to the top

When to vectorize?

Often in Matlab, loops can be avoided by vectorizing the statements inside. In the following examples, a for loop can easily be replaced with a single of vectorized code. Notice that the print statements have also been vectorized.

Example

% for-loop : y = 10*x + 1
x = rand(1,5);
y = zeros(size(x));  % Avoid warnings!
for i = 1:5,
    y(i) = 10*x(i) + 1;
    fprintf('x(%d) = %8.4f; y(%d) = %8.4f\n',i,x(i),i,y(i));
end
x(1) =   0.0497; y(1) =   1.4965
x(2) =   0.9027; y(2) =  10.0272
x(3) =   0.9448; y(3) =  10.4479
x(4) =   0.4909; y(4) =   5.9086
x(5) =   0.4893; y(5) =   5.8925
% Vectorized equivalent (preferable!)
y = 10*x + 1;

% Vectorized print statement
fprintf('x(%d) = %8.4f; y(%d) = %8.4f\n',[1:5; x; 1:5; y]);
x(1) =   0.0497; y(1) =   1.4965
x(2) =   0.9027; y(2) =  10.0272
x(3) =   0.9448; y(3) =  10.4479
x(4) =   0.4909; y(4) =   5.9086
x(5) =   0.4893; y(5) =   5.8925

Example

% for-loop : y = sin(pi*x/4) over  [0,2*pi]
for j = 1:9,
    y(j) = sin(pi*(j-1)/4);
    fprintf('y(%d) = %16.8f\n',j,y(j));
end
y(1) =       0.00000000
y(2) =       0.70710678
y(3) =       1.00000000
y(4) =       0.70710678
y(5) =       0.00000000
y(6) =      -0.70710678
y(7) =      -1.00000000
y(8) =      -0.70710678
y(9) =      -0.00000000
% vectorized equivalent (preferable!)
y = sin(pi*((0:8)/4));    % Parenthesis around  (0:8) are important here!

% Vectorized print statement
fprintf('y(%d) = %16.8f\n',[1:9; y]);
y(1) =       0.00000000
y(2) =       0.70710678
y(3) =       1.00000000
y(4) =       0.70710678
y(5) =       0.00000000
y(6) =      -0.70710678
y(7) =      -1.00000000
y(8) =      -0.70710678
y(9) =      -0.00000000

Example

% for-loop : Cumulative summation
s = 0;
y = zeros(1,10);
for k = 1:10,
    s = s + k;
    y(k) = s;
    fprintf('Sum of the numbers 1 to %2d : %5d\n',k, y(k));
end
Sum of the numbers 1 to  1 :     1
Sum of the numbers 1 to  2 :     3
Sum of the numbers 1 to  3 :     6
Sum of the numbers 1 to  4 :    10
Sum of the numbers 1 to  5 :    15
Sum of the numbers 1 to  6 :    21
Sum of the numbers 1 to  7 :    28
Sum of the numbers 1 to  8 :    36
Sum of the numbers 1 to  9 :    45
Sum of the numbers 1 to 10 :    55
% vectorized equivalent
y = cumsum(1:10);

% Vectorized print statement
fprintf('Sum of the numbers 1 to %2d : %5d\n',[1:10; y]);
Sum of the numbers 1 to  1 :     1
Sum of the numbers 1 to  2 :     3
Sum of the numbers 1 to  3 :     6
Sum of the numbers 1 to  4 :    10
Sum of the numbers 1 to  5 :    15
Sum of the numbers 1 to  6 :    21
Sum of the numbers 1 to  7 :    28
Sum of the numbers 1 to  8 :    36
Sum of the numbers 1 to  9 :    45
Sum of the numbers 1 to 10 :    55

Example

Sometimes, vectorization will be many times faster than an equivalent loop. For example,

N = 1e7;
th = linspace(0,2*pi,N);
tic
for i = 1:N,
    y(i) = sin(th(i));
end
t1 = toc;
% Vectorized statement
tic
y = sin(th);
t2 = toc;

fprintf('Time in loop                  : %8.4f\n',t1);
fprintf('Time in vectorized statement  : %8.4f\n',t2);
fprintf('The vectorized statement is %6.2f times faster\n',t1/t2);
Time in loop                  :   9.5433
Time in vectorized statement  :   0.0928
The vectorized statement is 102.83 times faster

There are many more examples of the above in which a vectorized statement is far preferable to using a loop.

Back to the top

When to use a for-loop?

While many common mathematical statements can be easily vectorized (and should be!) many complex programming tasks are better left in a loop. Sometimes, there is just no obvious way to vectorized the statement without either making the code difficult to read, or because the dependencies among loop iterates make the vectorized version inefficient. Below is an example of a programming task that is sufficiently complex, that it is better left in a loop. Note that inside the loop, we are still using array vectorization.

% -------------------------------------------------------------------
% Compute the minimum and maximum distance between all possible pairs of
% points in a set of points (x(i),y(i), i = 1,...n.
% -------------------------------------------------------------------
n = 15;
x = rand(1,n);    % x-coordinates, chosen at random from [0,1]
y = rand(1,n);    % y-coordinates, chosen at random from [0,1]

dmax = 0;
dmin = 100;
for i = 1:n,
    % Compute the distance between the point (x(i),y(i)) and the
    % array of points (x,y).  first, remove x(i),y(i) from
    % list (so the minimum isn't just 0!).
    x1 = x;
    y1 = y;
    x1(i) = [];   % Remove x(i) from list
    y1(i) = [];   % Remove y(i) from list

    % This is a vectorized statement.
    d = sqrt((x(i) - x1).^2 + (y(i) - y1).^2);

    % Find the maximum value in the array [d dmax]
    dmax = max([d dmax]);

    % Find the minimum value in the array [d dmax]
    dmin = min([d dmin]);

    % Plot the line connecting the points (x(i),y(i)) each  point in the
    % array (x,y).
    % This loop is "nested" inside of our outer loop.  While we could
    % vectorize this loop, it might not be so easy to read, and probably
    % doesn't save us much time.
    for j = 1:n,
        plot([x(i) x(j)],[y(i),y(j)],'b-','linewidth',2);
        hold on;
    end
end
fprintf('The minimum distance is %8.4f\n',dmin);
fprintf('The maximum distance is %8.4f\n',dmax);

% Plot a symbol at each point and add a title and axes labels.
plot(x,y,'r.','markersize',30,'linewidth',2);
set(gca,'fontsize',16,'fontweight','bold')
title('Point cloud');
xlabel('x-coordinate','fontsize',16);
ylabel('y-coordinate','fontsize',16);
axis([0 1 0 1]);

% Fix aspect ratio so the plot is square.
axis square;
The minimum distance is   0.0142
The maximum distance is   1.1081

Back to the top

Lab exercises

Associate each of the Matlab functions min, max, sum, prod, cumsum, cumprod, mean, median, std with exactly one mathematical expression below. Then, compute the value of each mathematical expression by two different ways:
  1. Using a single Matlab function
  2. Using a for loop
Compare your results to make sure you get the same result for each case.

Put all of your commands into a script containing your solution to each problem. To start, first create an array $x$ of 100 random values using the rand function. For example,
x = rand(100,1);
You will use this array for each of the exercises.

Note: In most cases, it will be preferable to use the single Matlab command than the for loop!.
  1. $\displaystyle{\sum_{k=1}^{n} x_k}$
  2. $\displaystyle{\min_{1 \le k \le n} x_k}$
  3. $\displaystyle{\frac{1}{n}\sum_{k=1}^n {x_k}}$
  4. $\displaystyle{y_j = \prod_{k=1}^j {x_k}}$, for $j = 1,2,...,n$
  5. $\displaystyle{\sqrt{\frac{1}{n-1}\sum_{k=1}^n (x_k - \mu)^2}}$, where $\displaystyle{\mu = \frac{1}{n}\sum_{k=1}^n x_k}$
  6. $\displaystyle{n}$
  7. Find the value $\sigma$ in $x$ such that half of the values $x_k$ are less than $\sigma$ and half are greater than $\sigma$.
  8. $\displaystyle{\max_{1 \le k \le n} x_k}$
  9. $\displaystyle{y_j = \sum_{k=1}^j {x_k}}$ for $j = 1,2,...,n$
  10. $\displaystyle{\prod_{k=1}^{n} x_k}$

% Example : Problem 1 below can be computing using the 'sum' function
% and a 'for' loop.
n = 100;
x = rand(1,n);
s = 0;
for i = 1:n,
    s = s + x(i);
end
fprintf('Result from ''sum'' function  : %24.16f\n',sum(x));
fprintf('Result from the ''for'' loop  : %24.16f\n',s);
Result from 'sum' function  :      50.7943989679829642
Result from the 'for' loop  :      50.7943989679829642

Compare your answers with the solutions.

Back to the top

Get the code

Do you want to try the above code fragments on your own? Download the Matlab script that produces this page here. (lab_17.m)

Powered by MathJax

Published with MATLAB® 8.4