4 Logical Arrays and Data Analysis
For a computer program to have “intelligence”, it must be able to make decisions. The way computers do that is by making comparisons, such as “Is this variable greater than that one?” or “Is this variable equal to a certain value?” The operators that perform these comparisons are called relational operators. In many cases, it is useful to evaluate two or more conditions simultaneously; boolean operators (and, or and not) are used in conjunction with relationals to evaluate more complex conditions.
This chapter introduces the concepts of relational and boolean operations and shows how they are applied to arrays. Chapter 6 discusses use of relational and boolean expressions with the if
statement to make decisions (branching) in a program.
Lecture Video 4.1 – Introduction
You can download the Live Script
4.1 Relational Operators and Logical Values
Decision-making in computer programs is typically driven by logical comparisons: one action is performed if a condition is true, while another is performed if it is false. Conditions are expressed in terms of a comparison of two quantities by applying one or more of the following relational operators:
> greater than
< less than
>= greater than or equal to
<= less than or equal to
== is equal
~= is not equal
The result of applying one of these operators is either true (logical 1) or false (logical 0).
A few basic examples are shown below:
>> x = 5;
>> x > 4
ans =
logical
1
>> x < 4
ans =
logical
0
>> x == 15/3
ans =
logical
1
The result of relational operations can be stored in a variable for later reference:
>> x_is_negative = x<0
x_is_negative =
logical
0
It is a bad practice to apply the equality operator (==) to expressions involving floating-point numbers. Because of the finite precision with which numbers are stored in a computer, roundoff error will often cause values that should be equal to be unequal. For example:
>> lhs = 1 + (1/3) - 2*4.0/8.0
lhs =
0.3333
>> rhs = 1/3
rhs =
0.3333
>> lhs == rhs
ans =
logical
0
Although these two expressions are mathematically equal, their digital representations are slightly different. This can be seen by calculating the difference:
>> lhs - rhs
ans =
-5.551115123125783e-17
The usual practice with floating-point numbers is to set a tolerance and regard any value less than that tolerance as zero:
>> tolerance = 1.0e-9;
>> abs(lhs - rhs) < tolerance
ans =
logical
1
Lecture Video 4.2 – Relational Operators
Checkpoint 4.1: Relational Operators
4.2 Boolean Operators
In some cases, a decision is based on multiple conditions being true simultaneously. In other cases, it may be based on one of several conditions being true. It is common to make decisions this way in everyday life, as in these examples:
- I will go to see Top Gun: Maverick tomorrow if it is showing in the IMAX theater AND there are tickets available for the 7:00 show.
- I will take that job if they give me a raise over my current salary OR they give me a bigger office.
- I will go cycling this afternoon if it does NOT rain
In the first example, both conditions have to be true for the decision to be taken. In the second, if either or both conditions are true, the decision is taken.
In MATLAB and other programming languages, these kinds of compound conditions are implemented using boolean operators:
Operator for scalars | Operator for arrays | Name | Meaning |
&& | & | and | both conditions must be true |
|| | | | or | at least one of the conditions must be true |
~ | ~ | not | the condition is false |
Boolean operators are commonly used in conjunction with relational operators, as in this example:
>> x_is_real_positive = imag(x) == 0 && x > 0
This expression evaluates to true (logical 1) if and only if both conditions are true: x is real (its imaginary part is 0) and x is positive (greater than 0).
>> x_is_real_positive = imag(x) == 0 && x > 0
Another example, using the or operator:
>> y_outside_limits = y < 10 || y > 20
This expression is true if y is NOT between 10 and 20 inclusive.
Lecture Video 4.3 – Boolean Operators
Checkpoint 4.2: Boolean Operators
4.3 Order of Operations & Mixed Arithmetic-Logical Expressions
Relational and boolean operators can be combined with arithmetic operators to achieve something much like branching with an if statement (see Chapter 6). The key to using this technique is to understand two things:
- In MATLAB, boolean operators treat any number other than 0 as true, as in these examples:
>> ~100
ans =
logical
0
>> x = 3;
>> y = -1;
>> x && y
ans =
logical
1
>> y || 0
ans =
logical
1
2. When a logical 0 or 1 appears in an arithmetic expression, it is treated as an arithmetic 0 or 1, as in these examples:
>> w = x == 3
w =
logical
1
>> z = y < 0
z =
logical
1
>> w + z
ans =
2
Relational expressions can be added, and the result is the number of the expressions that are true. For example,
>> (pi > 3) + (exp(1) < 3) + (sin(pi/4) == cos(pi/4))
ans =
2
The first two of these expressions are unambiguously true; the third is true mathematically, but evaluates to false in a computer due to the finite precision with which floating-point numbers are represented. (Review section 4.1.)
This technique can be used to accomplish something much like and if…else structure, which is discussed in Chapter 6. Suppose you want to accomplish this operation:
- if x is positive, let y = 10
- if x is 0 or negative, let y = 20
One way to accomplish that is with this expression:
y = 10*(x > 0) + 20 * (x <= 0)
Since the two relational operators are complementary (assuming that x is real), one of the two terms is true (1), and the other is false (0); thus y will have the value 10 or 20, as intended:
>> x =-3;
>> y = 10*(x > 0) + 20 * (x <= 0)
y =
20
When arithmetic, relational, and boolean operators are combined in a complicated expression, the order of operations is as shown in this table:
With the exception of the not (~) operator, which is relatively high in precedence, the general order is arithmetic > relational > boolean.
Checkpionts 4.3 – 4.4: Order of Operations
4.4 Logical Arrays
When a relational operator is applied to an array, the result is a logical array – an array of true
/false
values (also called logical 1
/ logical 0
). For example, if these commands are executed:
>> A = 0:2:10;
>> A_gt_4 = A > 4 %Are the elements of A greater than 4?
A_gt_4 =
1×6 logical array
0 0 0 1 1 1
The first 3 elements of the resulting logical array are logical 0 (false), since the first 3 elements of A are not greater than 4. The last 3 elements are logical 1 (true), since the corresponding elements of A are greater than 4.
Multiple relational operators can be combined with boolean operators to determine which elements of an array meet a complex condition. For example, to determine which elements of A are between 5 and 9, inclusive:
>> A_bt_5n9 = A >= 5 & A <= 9
A_bt_5n9 =
1×6 logical array
0 0 0 1 1 0
>> name1 = 'George Washington'
>> is_o = name1 == 'o'
is_o =
1×17 logical array
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0
>> first6_presidents = ["Washington", "Adams", "Jefferson", "Madison", "Monroe", "Adams"];
>> is_Adams = first6_presidents == "Adams"
is_Adams =
1×6 logical array
0 1 0 0 0 1
Lecture Video 4.4 – Logical Arrays
Checkpoint Questions – Logical Arrays
4.5 Logical Indexing and the find()
Function
A powerful technique for analyzing data arrays is to use a logical array as an index; this picks out the values of the data array for which the logical array is true. This technique, logical indexing, is typically used in conjunction with a relational operator to choose the elements of an array that meet a certain condition. For example, suppose you want to take the average of only the positive numbers in an array:
>> X = [-5, 7, -2, -4, 8, 3, 0, -6, 5];
X_pos = X (X > 0)
X_pos =
7 8 3 5
>> avg_pos = mean (X_pos)
avg_pos =
5.7500
>>
The expression X (X > 0)
picks out only those elements of X that meet the condition, X > 0
.
Logical indexing can also be used between two arrays, provided that they have the same dimensions. Suppose there are two arrays containing daily high temperatures and precipitation levels. To pick out the high temperatures on the days when it rained or snowed:
>> temperature = [41, 37, 28, 23, 36, 44, 50];
>> precipitation = [0, 0, 1.2, 0.3, 0, 2.5, 0.3];
>> temp_wet_days = temperature (precipitation > 0)
temp_wet_days =
28 23 44 50
Logical indexing is used to extract the values of an array that meet a certain condition. In some cases, it is useful to know the indices of the elements that meet the condition. For example, in the previous example, we may want to determine the days when the high temperature was below freezing. The find() function is useful for this type of analysis. Fundamentally, find() returns the indices of all non-zero elements in an array. It is often used in conjunction with a logical array to find the indices of the elements that satisfy a condition.
>> freezing_days = find(temperature < 32)
freezing_days =
3 4
This tells us that the 3rd and 4th days had sub-freezing high temperatures.
The find() function can also return the index of the first or last occurrence(s) of a condition. For example, to determine the last day when the temperature was below freezing:
>>last_freeze = find (temperature < 32, 1, 'last')
last_freeze =
4
Replace 'last'
with 'first'
to determine the first occurrence of the condition. The number 1 can be replaced by any positive integer, n
, to determine the first or last n
occurrences.
Lecture Videos 4.5-4.6 – Logical Indexing and the find() Function
Checkpoint Questions – Logical Indexing
Find an error? Have a suggestion for improvement? Please submit this survey.