0% found this document useful (0 votes)
2 views

Compound Boolean Expressions

The document discusses compound Boolean expressions in C++, explaining how simple Boolean expressions can be combined using logical operators such as AND (&&), OR (||), and NOT (!). It emphasizes the importance of understanding operator precedence and short-circuit evaluation to avoid logical errors and improve performance in expressions. Additionally, it highlights common pitfalls in writing Boolean expressions and provides examples to illustrate correct usage.

Uploaded by

swati.dbit
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Compound Boolean Expressions

The document discusses compound Boolean expressions in C++, explaining how simple Boolean expressions can be combined using logical operators such as AND (&&), OR (||), and NOT (!). It emphasizes the importance of understanding operator precedence and short-circuit evaluation to avoid logical errors and improve performance in expressions. Additionally, it highlights common pitfalls in writing Boolean expressions and provides examples to illustrate correct usage.

Uploaded by

swati.dbit
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

5.6.

COMPOUND BOOLEAN EXPRESSIONS 100

int main() {
double d1 = 1.11 - 1.10,
d2 = 2.11 - 2.10;
cout << "d1 = " << d1 << endl;
cout << "d2 = " << d2 << endl;
if (d1 == d2)
cout << "Same" << endl;
else
cout << "Different" << endl;
cout << "d1 = " << setprecision(20) << d1 << endl;
cout << "d2 = " << setprecision(20) << d2 << endl;
}

In Listing 5.5 (samedifferent.cpp) the displayed values of d1 and d2 are rounded so they appear equivalent,
but internally the exact representations are slightly different. By including the header iomanip we can
use the setprecision stream manipulator to force cout to display more decimal places in the floating-
point number it prints. Observe from the output of Listing 5.5 (samedifferent.cpp) that the two quantities
that should be identically 0.01 are actually slightly different.

d1 = 0.01
d2 = 0.01
Different
d1 = 0.010000000000000009
d2 = 0.0099999999999997868

This result should not discourage you from using floating-point numbers where they truly are needed.
In Section 9.4.6 we will see how to handle floating-point comparisons properly.

5.6 Compound Boolean Expressions

Simple Boolean expressions, each involving one relational operator, can be combined into more complex
Boolean expressions using the logical operators && (and), || (or), and ! (not). A combination of two or
more Boolean expressions using logical operators is called a compound Boolean expression.
To introduce compound Boolean expressions, consider a computer science degree that requires, among
other computing courses, Operating Systems and Programming Languages. If we isolate those two courses,
we can say a student must successfully complete both Operating Systems and Programming Languages to
qualify for the degree. A student that passes Operating Systems but not Programming Languages will not
have met the requirements. Similarly, Programming Languages without Operating Systems is insufficient,
and a student completing neither Operating Systems nor Programming Languages surely does not qualify.
Logical AND works in exactly the same way. If e1 and e2 are two Boolean expressions, e1 && e2 is true
only if e1 and e2 are both true; if either one is false or both are false, the compound expression is false.
To illustrate logical OR, consider two mathematics courses, Differential Equations and Linear Algebra.
A computer science degree requires one of those two courses. A student who successfully completes
Differential Equations but does not take Linear Algebra meets the requirement. Similarly, a student may
take Linear Algebra but not Differential Equations. It is important to note the a student may elect to take

©2015 Richard L. Halterman Draft date: February 26, 2015


5.6. COMPOUND BOOLEAN EXPRESSIONS 101

e1 e2 e1 && e2 e1 || e2 !e1
false false false false true
false true false true true
true false false true false
true true true true false

Table 5.3: Logical operators—e1 and e2 are Boolean expressions

both Differential Equations and Linear Algebra (perhaps on the way to a mathematics minor), but the
requirement is no less fulfilled.
Logical OR works in a similar fashion. Given our Boolean expressions e1 and e2 , the compound ex-
pression e1 || e2 is false only if e1 and e2 are both false; if either one is true or both are true, the compound
expression is true. Note that logical OR is an inclusive or, not an exclusive or. In informal conversion we
often imply exclusive or in a statement like “Would you like cake or ice cream for dessert?” The implica-
tion is one or the other, not both. In computer programming the or is inclusive; if both subexpressions in
an or expression are true, the or expression is true.
Logical NOT simply reverses the truth value of the expression to which it is applied. If e is a true
Boolean expression, !e is false; if e is false, !e is true.
Table 5.3 is called a truth table. It shows all the combinations of truth values for two simple expres-
sions and the values of compound Boolean expressions built from applying the &&, ||, and ! C++ logical
operators.
Both && and || are binary operators; that is, they require two operands, both of which must be Boolean
expressions. Logical not (!) is a unary operator (see Section 4.1); it requires a single Boolean operand
immediately to its right.
Operator ! has higher precedence than both && and ||. && has higher precedence than ||. && and ||
are left associative; ! is right associative. && and || have lower precedence than any other binary operator
except assignment. This means the expression

x <= y && x <= z

is evaluated

(x <= y) && (x <= z)

Some programmers prefer to use the parentheses as shown here even though they are not required. The
parentheses improve the readability of complex expressions, and the compiled code is no less efficient.

©2015 Richard L. Halterman Draft date: February 26, 2015


5.6. COMPOUND BOOLEAN EXPRESSIONS 102

The relational operators such as < compare two operands. The result of the com-
parison is a Boolean value, which is freely convertible to an integer. The misappli-
cation of relational operators can lead to surprising results; consider, for example,
the expression
1 <= x <= 10
This expression is always true, regardless of the value of x! If the programmer’s
intent is to represent the mathematical notion of x falling within the range 1...10
inclusive, as in 1 ≤ x ≤ 10, the above C++ expression is not equivalent.

The expression
1 <= x <= 10
is evaluated as
(1 <= x) <= 10
If x is greater than or equal to one, the subexpression 1 ∼ <= ∼ x evaluates to
true, or integer 1. Integer 1, however, is always less than 10, so the overall expres-
sion is true. If instead x is less than one, the subexpression 1 ∼ <= ∼ x evaluates
to false, or integer 0. Integer 0 is always less than 10, so the overall expression is
true. The problem is due to the fact that C++ does not strictly distinguish between
Boolean and integer values.

A correct way to represent the mathematical notion of 1 ≤ x ≤ 10 is


1 <= x && x <= 10
In this case x must simultaneously be greater than or equal to 1 and less than
or equal to 10. The revised Boolean expression is a little more verbose than the
mathematical representation, but it is the correct formulation for C++.

The following section of code assigns the indicated values to a bool:


bool b;
int x = 10;
int y = 20;
b = (x == 10); // assigns true to b
b = (x != 10); // assigns false to b
b = (x == 10 && y == 20); // assigns true to b
b = (x != 10 && y == 20); // assigns false to b
b = (x == 10 && y != 20); // assigns false to b
b = (x != 10 && y != 20); // assigns false to b
b = (x == 10 || y == 20); // assigns true to b
b = (x != 10 || y == 20); // assigns true to b
b = (x == 10 || y != 20); // assigns true to b
b = (x != 10 || y != 20); // assigns false to b

Convince yourself that the following expressions are equivalent:


(x != y)

©2015 Richard L. Halterman Draft date: February 26, 2015


5.6. COMPOUND BOOLEAN EXPRESSIONS 103

!(x == y)
(x < y || x > y)

In the expression e1 && e2 both subexpressions e1 and e2 must be true for the overall expression to be
true. Since the && operator evaluates left to right, this means that if e1 is false, there is no need to evaluate
e2 . If e1 is false, no value of e2 can make the expression e1 && e2 true. The logical and operator first tests the
expression to its left. If it finds the expression to be false, it does not bother to check the right expression.
This approach is called short-circuit evaluation. In a similar fashion, in the expression e1 || e2 , if e1 is
true, then it does not matter what value e2 has—a logical or expression is true unless both subexpressions
are false. The || operator uses short-circuit evaluation also.
Why is short-circuit evaluation important? Two situations show why it is important to consider:

• The order of the subexpressions can affect performance. When a program is running, complex ex-
pressions require more time for the computer to evaluate than simpler expressions. We classify an
expression that takes a relatively long time to evaluate as an expensive expression. If a compound
Boolean expression is made up of an expensive Boolean subexpression and an less expensive Boolean
subexpression, and the order of evaluation of the two expressions does not affect the behavior of the
program, then place the more expensive Boolean expression second. If the first subexpression is false
and && is being used, then the expensive second subexpression is not evaluated; if the first subex-
pression is true and || is being used, then, again, the expensive second subexpression is avoided.

• Subexpressions can be ordered to prevent run-time errors. This is especially true when one of the
subexpressions depends on the other in some way. Consider the following expression:

(x != 0) && (z/x > 1)

Here, if x is zero, the division by zero is avoided. If the subexpressions were switched, a run-time
error would result if x is zero.

©2015 Richard L. Halterman Draft date: February 26, 2015


5.7. NESTED CONDITIONALS 104

Arity Operators Associativity


unary (post) ++, (post) --, static_cast
unary (pre) ++, (pre) --, !, +, -
binary *, /, % left
binary +, - left
binary <<, >> left
binary >, <, >=, <= left
binary ==, != left
binary && left
binary || left
binary =, +=, -=, *=, /=, %= right

Table 5.4: Precedence of C++ Operators (High to Low)

Suppose you wish to print the word “OK” if a variable x is 1, 2, or 3. An informal


translation from English might yield:
if (x == 1 || 2 || 3)
cout << "OK" << endl;
Unfortunately, x’s value is irrelevant; the code always prints the word “OK.” Since
the == operator has lower precedence than ||, the expression
x == 1 || 2 || 3
is interpreted as
(x == 1) || 2 || 3
The expression x == 1 is either true or false, but integer 2 is always interpreted
as true, and integer 3 is interpreted as true is as well.

The correct statement would be


if (x == 1 || x == 2 || x == 3)
cout << "OK" << endl;
The revised Boolean expression is more verbose and less similar to the English
rendition, but it is the correct formulation for C++.

Our current list of C++ operators is shown in Table 5.4.

5.7 Nested Conditionals

The statements in the body of the if or the else may be any C++ statements, including other if/else
statements. We can use nested if statements to build arbitrarily complex control flow logic. Consider
Listing 5.6 (checkrange.cpp) that determines if a number is between 0 and 10, inclusive.

Listing 5.6: checkrange.cpp


#include <iostream>

©2015 Richard L. Halterman Draft date: February 26, 2015

You might also like