Loops and one dimensional arrays


Topics in this lab

Introduction

So far, we have covered how to use linspace to construct a one-dimensional array useful for plotting. In this lab, we want to explore other ways to create one-dimensional arrays.

We will also learn how to retrieve particular entries of an array, as well as how to use the for loop to control the flow execution of statements in a script.

Back to the top

Using the colon operator to construct arrays

We have already seen how we can construct one dimensional arrays using the linspace command. We have also seen how to use square brackets to enclose a list of numbers:

x = [1 3 5 7 9]
x =

     1     3     5     7     9

Another method to construct an array that is very similar to the linspace makes use of the : operator. For example,

v = 1:10
v =

     1     2     3     4     5     6     7     8     9    10

constructs an array of 10 integers between 1 and 10. A more general use of the colon (:) operator allows us to specify the step size we wish to take.

v = 0:2:20
v =

     0     2     4     6     8    10    12    14    16    18    20

is a list of even numbers between 0 and 20. The step size can also be negative. For example,

v = 5:-1:-5
v =

     5     4     3     2     1     0    -1    -2    -3    -4    -5

or

v = 50:-5:0
v =

    50    45    40    35    30    25    20    15    10     5     0

Querying the help documentation on the the colon operator gives us:

>> help colon
 :  Colon.
    J:K  is the same as [J, J+1, ..., K].
    J:K  is empty if J > K.
    J:D:K  is the same as [J, J+D, ..., J+m*D] where m = fix((K-J)/D).
    J:D:K  is empty if D == 0, if D > 0 and J > K, or if D < 0 and J < K.
.............

Like linspace, the colon operator automatically fills in entries in an array with equally spaced points. However, we can get some unexpected results if the endpoints we specify are not evenly divided by the stepsize we specify. Consider the following example

v = 0:3:10
v =

     0     3     6     9

We notice that the endpoint 10 does not appear in the array. The reason for this is that 10 is not evenly divided by 3, so is not reached in steps of 3 starting from 0. Rather than shorten the last step size, Matlab only includes those values between the specified endpoints that are even multiples of the step size and shifted by the first endpoint.

Carrying the above example further, we see that it is possible to construct an array that contains only a single element :

v = 10:15:20
v =

    10

In this case, one step already takes us beyond the specified endpoint, and so the vector only contains the starting point 10.

What happens if the step size does not have the same sign as our end value minus our start value? In this case, Matlab will create an empty array. The following example illustrates this.

v = 0:-1:10
v =

   Empty matrix: 1-by-0

Here, 10-0 is positive, but our stepsize -1 is negative, and so an empty array is created. Any time we use a step size of 0, we will also get an empty array. The simplest empty array in Matlab is an empty pair of square brackets ([]).

v = []
v =

     []

The length of an empty array is 0.

length(v)
ans =

     0

Back to the top

The colon operator and the linspace command

We can use the colon operator to construct the same array that linspace creates. To describe how the colon operator and the linspace are related, we consider a vector with a start point a, end point b and n equally spaced entries. Using linspace, we create this vector as

a = -1;    % start of the linspace vector
b = 1;     % end of the linspace vector
n = 11;    % Number of points in the linspace vector
x1 = linspace(a,b,n)
x1 =

  Columns 1 through 7

   -1.0000   -0.8000   -0.6000   -0.4000   -0.2000         0    0.2000

  Columns 8 through 11

    0.4000    0.6000    0.8000    1.0000

To construct the same same vector using the colon operator, we need to first compute the step size that linspace used.

step = (b - a)/(n-1)    % Step size used by linspace
step =

    0.2000

And then we can construct the same vector using the colon operator.

x2 = a:step:b
x2 =

  Columns 1 through 7

   -1.0000   -0.8000   -0.6000   -0.4000   -0.2000         0    0.2000

  Columns 8 through 11

    0.4000    0.6000    0.8000    1.0000

A word of warning : Whereas the linspace is guaranteed to have exactly a and b as endpoints, and exactly n entries, this is not guaranteed when using the colon operator. We have already seen above that the : operator will leave off the final entry if it cannot be expressed in terms of multiples of the stepsize. This can also happen, even when the step sizes are only nearly divide the interval.

step = (1+1e-15)/5;
v = 0:step:1
v =

         0    0.2000    0.4000    0.6000    0.8000

In this example, we divided an interval slightly larger than $1$ by the $5$, and then used this step size to construct an array. The final element in the array is not 1, as might be expected, but rather is a value very close to 0.8. To see why this is, we print out the value 5*step and see that it is in fact larger than 1, if only by a very small amount.

format long e
5*step
ans =

     1.000000000000001e+00

Back to the top

Indexing arrays

To retrieve a single entry from a one-dimensional array, we can use the parenthesis operator () with an argument indicating the entry we want. First, we will create an array of random numbers using the rand function.

format short e
v = rand(1,10)
v =

  Columns 1 through 6

   1.4182e-01   8.8442e-01   1.9762e-02   3.4269e-01   2.3831e-01   9.8456e-01

  Columns 7 through 10

   8.4660e-01   7.9451e-01   9.0028e-01   7.8010e-01

We can retrieve the second entry in v as

v(2)
ans =

   8.8442e-01

We can also retrieve multiple elements of an array by using an array of index locations. Suppose we wanted to retrieve every other element in an array of 7 elements. We pass an integer sequence indicating the entries we want to the () operator.

v([1,3,5,7])
ans =

   1.4182e-01   1.9762e-02   2.3831e-01   8.4660e-01

Alternatively, we could do the following.

v(1:2:7)
ans =

   1.4182e-01   1.9762e-02   2.3831e-01   8.4660e-01

In both cases, we used an array of integers to specify the desired indices. We can also use the colon operator to reorder the entries in the array :

w = v(10:-1:1)
w =

  Columns 1 through 6

   7.8010e-01   9.0028e-01   7.9451e-01   8.4660e-01   9.8456e-01   2.3831e-01

  Columns 7 through 10

   3.4269e-01   1.9762e-02   8.8442e-01   1.4182e-01

In fact we can choose entries in order, even duplicating entries :

w = v([5 7 2 9 9 3 2 2])
w =

  Columns 1 through 6

   2.3831e-01   8.4660e-01   8.8442e-01   9.0028e-01   9.0028e-01   1.9762e-02

  Columns 7 through 8

   8.8442e-01   8.8442e-01

In Matlab, the first entry in an array is always 1. If we try to index the zero-th element of an array, we can expect an error

v(0)
Subscript indices must either be real positive integers or logicals.

If we use an index that is larger than the number of elements that we have, we can also expect an error:

v(12)
Index exceeds matrix dimensions.

What if you want to get the last three entries in an array? Since the length of an array is often one of the variables in the script you are writing, you might consider doing the following.

n = length(v);
v([n-2 n-1 n])
ans =

   7.9451e-01   9.0028e-01   7.8010e-01

Here, we used the Matlab length function to find out how long v is.

The above situation arises so often, that Matlab has built into the language a way to get the last entries of a vector by allowing the use of the end keyword inside of arrays. This statement retrieves the last entry in an array

v(end)
ans =

   7.8010e-01

To retrieve the last three entries in an array, you can use the end as if it were the actual variable or constant storing the length of the array. For example,

v([end-2 end-1 end])
ans =

   7.9451e-01   9.0028e-01   7.8010e-01

or simply

v(end-2:end)
ans =

   7.9451e-01   9.0028e-01   7.8010e-01

Back to the top

Simple array concatenation

We can always construct a new array by glueing two arrays together. For example, suppose we have two row vectors u and v. We can construct a new array w by glueing, or concatenating u and v together using square brackets.

u = -5:-2
u =

    -5    -4    -3    -2

v = 21:27
v =

    21    22    23    24    25    26    27

w1 = [u v]
w1 =

    -5    -4    -3    -2    21    22    23    24    25    26    27

w2 = [v u]
w2 =

    21    22    23    24    25    26    27    -5    -4    -3    -2

The resulting arrays w1 and w2 each have length equal to the sums of the lengths of u and v.

Example : Approximating $\pi$


Suppose we want to approximate the value of $\pi$ by computing the length of an n-sided the polygon whose vertices are on the quarter circle of radius 2, as shown below.


To approximate $\pi$, we compute the perimeter of the polygon described by this quarter circle.



We construct arrays x and y containing the coordinates of each vertex of the quarter of a circle (including the origin), and then compute the distance between each neighboring pair of vertices $(x_i,y_i)$ and $(x_{i+1},y_{i+1})$. For convenience, we use array concatenation to add the first point $(x_1,y_1)$ to the end of our vertex list so that we have $x_{n+1} = x_1$ and $y_{n+1} = y_1$. We can then compute the length of each side of the polygon with a single Matlab statement and then sum the lengths to get the perimeter of the polygon. By subtracting out the length of the edges that lie on the x and y axes, we can get an approximation to $\pi$.

% ---------------------------------------------------------
% Approximate pi by computing the perimeter of a semicircle
% ---------------------------------------------------------

n = 8;                % Number of vertices on the polygon
R = 2;                   % Radius of the circle
th = pi*(0:n)/(2*n);     % Angles 'theta' between 0 and pi/2
x = R*cos(th);           % x-coordinates along the semicircle
y = R*sin(th);           % y-coordinates along the semicircle

% Construct the vertex list, including the point (0,0).   Wrap the first
% point around to the end of the list.
x = [x 0 x(1)];
y = [y 0 y(1)];

% Compute distances between each neighboring pair of points
d = sqrt((x(1:end-1) - x(2:end)).^2 + (y(1:end-1) - y(2:end)).^2);

% Approximate pi by adding up the lengths of the edges of the polygon, and
% and subtracting out the segments that lie along the x- and y-axis.
pi_approx = sum(d)-4;

% Print out the results
fprintf('Approximation to pi %24.16f\n',pi_approx);
fprintf('Matlab value ''pi''   %24.16f\n',pi);
fprintf('Error               %24.8e\n',abs(pi_approx - pi));
Approximation to pi       3.1365484905459393
Matlab value 'pi'         3.1415926535897931
Error                         5.04416304e-03

This approximation uses the sum function which we will discuss in more detail below.

Back to the top

Introduction to 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!\n');
end
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

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\n');
end
Three brown bears
Three brown bears
Three brown bears
% Example 2
for x = [3.1 5.6],
    fprintf('A couple of ducks\n');
end
A couple of ducks
A couple of ducks
% Example 3
for j = 10:-2:0,
    fprintf('Six Simple Simons sitting on a stump\n');
end
Six Simple Simons sitting on a stump
Six Simple Simons sitting on a stump
Six Simple Simons sitting on a stump
Six Simple Simons sitting on a stump
Six Simple Simons sitting on a stump
Six Simple Simons sitting on a stump
% 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 the above examples, we did not make use of the actual values in the loop index array, only the length of the array. But in most cases, the statements enclosed by the for loop will actually involve the value of the loop index variable as well. 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.2088
x( 9) =   0.6964
x( 8) =   0.0323
x( 7) =   0.9086
x( 6) =   0.3374
x( 5) =   0.2892
x( 4) =   0.6645
x( 3) =   0.7427
x( 2) =   0.3211
x( 1) =   0.8365
% 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.


Example : Finding the maximum distance between pairs of points


For a more complete example that requires the use of a for loop, we consider the problem of finding the maximum distance between all possible pairs of points with coordinates described by the arrays x and y. We will also include a loop in which we plot the line between a point in the array and each of the other points.

% -------------------------------------------------------------------
% Compute the maximum distance between all possible pairs of points
% in a set of points (xi,yi), 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;
for i = 1:n,
    % Compute the distance between the point (x(i),y(i)) and the
    % array of points (x,y).
    d = sqrt((x(i) - x).^2 + (y(i) - y).^2);

    % Find the maximum value in the array [d dmax] (see 'max' function
    % below).
    dmax = max([d dmax]);

    % Plot the line connecting the points (x(i),y(i)) each  point in (x,y)
    for j = 1:n,
        plot([x(i) x(j)],[y(i),y(j)],'r-');
        hold on;
    end
end
fprintf('The maximum distance is %12.4e\n',dmax);

% Plot a symbol at each point and add a title and axes labels.
plot(x,y,'bp','markersize',15,'linewidth',2);
set(gca,'fontsize',16,'fontweight','bold')
title('Point star');
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 maximum distance is   9.8484e-01

Back to the top

Simple array functions for one-dimensional arrays

Matlab has several functions which operate on one-dimensional arrays. We have already see one such function, the length function, which returns the number of elements in the array.

x = 0:25:1000;
length(x)
ans =

    41

Other such Matlab functions are convenient in that they allow us to avoid the use of for loops in many cases. A partial list of such functions include min, max, sum, prod, cumsum, cumprod, mean, median, std and sort. Below, we use an example to illustrate how each function works.

x = rand(1,1000);
v = 1:10;

Example 1 : The minimum and maximum values of an array


fprintf('The minimum value in array x is %16.8f\n',min(x));
fprintf('The maximum value in array x is %16.8f\n',max(x));
The minimum value in array x is       0.00007393
The maximum value in array x is       0.99944897

Example 2 : The total sum and product of the entries


fprintf('The sum of the values in v is     %16.8e\n',sum(v));
fprintf('The product of the values in v is %16.8e\n',prod(v));
The sum of the values in v is       5.50000000e+01
The product of the values in v is   3.62880000e+06

Example 3 : The cumulative sums and products of the entries


fprintf('The array of cumulative sums of the entries of v are\n');
cumsum(v)
The array of cumulative sums of the entries of v are

ans =

     1     3     6    10    15    21    28    36    45    55

fprintf('The array of cumulative products of v are\n');
format short e;
cumprod(v)
The array of cumulative products of v are

ans =

  Columns 1 through 6

           1           2           6          24         120         720

  Columns 7 through 10

        5040       40320      362880     3628800

Example 4 : The mean, median and standard deviation


fprintf('The mean of the values of x :                  %16.8f\n',mean(x));
fprintf('The median of the values of x is :             %16.8f\n',median(x));
fprintf('The standard deviation of the values of x is : %16.8f\n',std(x));
The mean of the values of x :                        0.51140513
The median of the values of x is :                   0.50865724
The standard deviation of the values of x is :       0.28466467

Example 5 : A sorted list of the numbers.


y = sort(x);

To see that we really have a sorted list, we will compare the first entry of y to the minimum value of x, and the last entry of y to the maximum value of x.

fprintf('The minimum value of x : %24.16f\n',min(x));
fprintf('The first entry of y   : %24.16f\n',y(1));
The minimum value of x :       0.0000739335770539
The first entry of y   :       0.0000739335770539
fprintf('The maximum value of x : %24.16f\n',max(x));
fprintf('The last entry of y    : %24.16f\n',y(end));
The maximum value of x :       0.9994489713903782
The last entry of y    :       0.9994489713903782

Most of the functions illustrated above can be used in many ways, not just in the manner shown above. For example, the functions min and max can each take two array arguments, allowing us to easily compare the size of corresponding entries in two arrays.

In the following example, we compare the entries in an array x of random values to the value 0.5 and create a new array in which the values in x larger than 0.5 have been replaced by 0.5.

format short;
x = rand(1,10)
x =

  Columns 1 through 7

    0.3807    0.2807    0.1799    0.1273    0.0157    0.7531    0.5050

  Columns 8 through 10

    0.7221    0.7611    0.2689

y = min(0.5,x)
y =

  Columns 1 through 7

    0.3807    0.2807    0.1799    0.1273    0.0157    0.5000    0.5000

  Columns 8 through 10

    0.5000    0.5000    0.2689

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  :      52.1287210881945313
Result from the 'for' loop  :      52.1287210881945313

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_4.m)

Powered by MathJax

Published with MATLAB® 8.2