Single Way and Multiway Selection-Relational and Logical Operators
Single Way and Multiway Selection-Relational and Logical Operators
Relational Operators
• Relational operators:
o Allow comparisons
o Require two operands (binary)
o Return 1 (or nonzero integer) if expression true, otherwise 0 false
• Comparing values of different data types may produce unpredictable results
o For example: 6 < '5' (compares integer 6 with character '5')
!= not equal to
x != y
***BE CAREFUL!
'a' < 'A' evaluates to false!
***Under the ASCII Collating Sequence: numbers < ucase letters < lcase letters
ASCII Chart
str1 < str2 //true: second character 'e' less than 'i'
str4 < str3 //false: first character 'B' greater than 'A'
str3 >= "An" //true: characters are equal, but str3 is longer than "An"
***Caution!***
Sometimes, programs are required to compare numbers and/or variable values. For
example:
int x = 5; // integers have no precision issues
if (x==5)
cout << "x equals 5" << endl;
else
cout << "x does not equal 5" << endl;
if (fTotal == 2.468)
cout << "fTotal is 2.468";
else
cout << "fTotal is not 2.468";
For this reason, comparison operators >, >=, <, and <= may produce incorrect
results when comparing floating point numbers. Solution: Code to allow for some
tolerance.
if (x > 5.01) && (x < 5.03) cout << "Equal";
• Logical (Boolean) operators take logical values as operands, and yield logical values
as results
• Three logical (Boolean) operators:
o ! (not)
o && (and)
o || (or)
• ! is unary; && and || are binary operators
• ! in front of logical expression reverses value
• true and false are keywords
• true (nonzero)
• false (0)
To clarify the differences between using the logical (boolean) operators AND &&, OR ||, and
bitwise operators AND &, OR |:
First of all, let me preface any comments by saying when using && or &, and || or |, ultimately
the results are the SAME. When using && or & operators, both operands must be true,
otherwise, false. When using || or | operators, both operands must be false, otherwise, true.
The difference lies in the evaluation PROCESS.
With respect to logical vs. bitwise operators, there is a difference between using the logical
"and" (&&), rather than the bitwise "and" (&). And, yes, there is a very important difference-
-and, no "one size fits all" solution:
When the logical (&&) operator is used to compare a logical expression, the compiler will stop
the evaluation upon the first false condition, unlike the & operator which will continue to
evaluate the ensuing expression(s) being compared.
if(++myVal % 2 == 0 && ++count < limit)
// Do something
If the left hand operand is evaluated to be false (++myVal % 2 == 0), the compiler will
stop and not evaluate the right-hand operand (++count < limit). More importantly, if myVal
is not an even number, count will NOT increment.
This may be fine, IF count doesn�t need to increment every time. Though, if it does, use the
bitwise "and" (&) operator to evaluate both expressions. As the following example:
if(++myVal % 2 == 0 & ++count < limit)
// Do something
Again, fundamentally, the logical result is the same (i.e., a truth table) for both & and &&:
"Do something" only will be executed if BOTH expressions are true. The benefit is that the
bitwise "and" (&) operator will allow count to increment.
On the other hand, you may not want the right hand expression to be evaluated (that is, use
&& not &). Example:
If(count > 0 && total/count > 5)
Here, it's easy to see that one would NOT want a compile or run-time error if the value of
count were 0!
Lastly, the same "truth table" logic holds true for logical "or" (||) vs. the bitwise "or" (|). That
is, the || operator is like && in that the right hand operand is NOT evaluated if the left hand
operand is TRUE. You would need to use | if you wanted BOTH expressions to be evaluated.
Using bool Data Type and Logical (Boolean) Expressions:
• bool data type uses logical (Boolean) values true and false
• bool, true, and false are reserved words
• Identifier true contains value 1
• Identifier false contains value 0
• Be careful when using logical expressions:
o 0 <= x <= 10 (Incorrect)
Always evaluates to true because 0 <= x evaluates to either 0 or 1, and 0 <=
10 is true and 1 <= 10 is true
o 0 <= x && x <= 10 (Correct)
Two operator characteristics determine how operands group with operators: precedence and
associativity. Precedence is the priority for grouping different types of operators with their
operands. Associativity is the left-to-right or right-to-left order for grouping operands to
operators that have the same precedence. An operator's precedence is meaningful only if
other operators with higher or lower precedence are present. Expressions with higher-
precedence operators are evaluated first. The grouping of operands can be forced by using
parentheses.
Also, operators follow a strict precedence, which defines the evaluation order of expressions
containing these operators. Operators associate with either the expression on their left or the
expression on their right; this is called "associativity." The following table shows the
precedence and associativity of C++ operators (from highest to lowest precedence).
Operators in the same segment of the table have equal precedence and are evaluated left to
right in an expression unless explicitly forced by parentheses.
Operator Precedence and Associativity 1
And...
Operator Precedence and Associativity 2
Mnemonic: "Math Relates Logically"
• Generally, the following 3 types of operators are evaluated in the following order: 1.
Mathematical, 2. Relational, 3. Logical
• Operators with same level of precedence evaluated from left to right
• Unary operators have higher order of precedence than binary operators:
e.g., logical not (!), unary minus (-), unary plus (+)
• Associativity is left to right for most mathematical, relational, and logical operators
• Unary operators are right associative: e.g., logical not (!), unary minus (-),
unary plus (+)--not including some postfix operators
• Parentheses can be used to override precedence
Order of Precedence Examples (for complete listing, see links above):
if (expression)
statement1;
statement2;
• if is reserved word
• expression must evaluate to true (nonzero) or false (0)
• statement1 executed if value of expression true
• statement1 bypassed if value false; program execution moves to statement2
• statement2 is executed regardless
{
statement1;
statement2;
.
.
.
statementn;
}
{
if (condition1)
statement1;
else if (condition2)
statement2;
. . .
else if (condition-n)
statement-n;
else
statement-z;
}
Example 1:
{
if (x < 0)
y = -1;
else if (x == 0)
y = 0;
else //(x > 0)
y = 1;
}
Example 2:
{
if (x < 0)
y = -1;
if (x == 0)
y = 0;
if (x > 0)
y = 1;
}
• Example 2 not recommended: a) not clear that only one statement will be executed
for given value of x; b) inefficient since all conditions are always tested!
switch Structures
case x2:
statements2;
break;
case x3:
statements3;
break;
default:
statements4;
break;
}
Example 2:
switch (integralTestExpression)
{
case value1: // taken if integralTestExpression == value1
statements...;
break; // necessary to exit switch
case value2:
case value3: // taken if integralTestExpression == value2 or == value3
statements...;
break;