CONDITIONS,
LOGICAL EXPRESSIONS, AND SELECTION CONTROL STRUCTURES (if,
if/else, switch, ?:)
TOPICS
Conditions and
Logical Expressions.
The if Statement (
if-then-else statement, if-then statement).
Nested if Statements
The switch Statement
The Conditional Operator (?:)
Sample Programs
OUTLINE
Conditions
and Logical Expressions
In Java, a condition is represented by a logical (Boolean) expression (an
expression that has a value of either true or false
when evaluated). These expressions are created using relational
operators; relational operators can be used to make comparisons in a program.
Logical Expressions (Boolean Expressions) = logical values + operations.
Result = trueor
false.
1. Relational Operators: > (greater than), < (less than), >= (greater than or equal to), <= (less than or equal to), == (equal to --> the equality operator), != (not equal to). Relational operators can be used with integral, floating-point, and char data types. They test a relationship between 2 values (binary operators) and they are used in expressions of this form:
ExpressionA Operator ExpressionB
Examples:
temperature > humidity
b * b - 4.0 * a * c > 0.0
abs (number ) == 35
initial != 'Q'More examples:
int x = 4;
int y = 6 ;
EXPRESSION
VALUE
x < y
TRUE
x + 2 < y
FALSE
x != y
TRUE
x + 3 >= y
TRUE
y == x
FALSE
y == x + 2
TRUE
Note: The assignment operator vs. the equality operator: Remember that Java uses = to denote assignment. If one language notation in Java could be singled out as causing the most logical errors it might well be the use of = as the relational operator "equals." To test whether two values are equal, you must use the = = operator. The classic mistake is to write a statement like this
if (x = 5) // assignment, not equality operator!
... ...This will generate a compile error in Java. It is very important to keep the = and = = operators distinct in your mind!
2. Relational Operators with Floating Point Types: Do not compare floating-point numbers for equality; approximate values, they are rarely exactly equal --> The comparison may not behave as you expect it to. Instead, test for near equality - compute the difference between the 2 numbers and check if the result is less than some max allowable difference.
Example:double x = 1.0;
double y = 3.0;
double z;
...
z = x/y;
...
if (x == z * y)... // x will not be 1.0, but 0.99999
if ((x - z * y) < 0.00001)... // close enough3. Logical Operators: ! (NOT), &&(AND), || (OR)
Operator
Meaning
Syntax
&&
AND
Expression1 && Expression2
| |
OR
Expression1 || Expression2
!
NOT
!Expression1
Logical Expression
Meaning
Type
Description
!P
NOT P
Unary
!P is false if P is true; !P is true if P is false
P && Q
P AND Q
Binary
P && Q is true if BOTH P and Q are true. It is false otherwise
P || Q
P OR Q
Binary
P || Q is true if either P or Q or both are true. It is false otherwise.
Note: Computer science distinguishes between two OR operations: the INCLUSIVE OR which is the default meaning of OR and the EXCLUSIVE OR. Informally, INCLUSIVE OR means "either one or the other or both," whereas EXCLUSIVE OR means "either one or the other but not both." In relating the OR operation to English usage, the subtlety is this: In a programming language, OR means INCLUSIVE OR, whereas in English, OR usually means EXCLUSIVE OR. "Your dinner comes with mashed potatoes or French fries" implicitly means "... but not both."
We define Boolean operators by truth tables, which give the desired output for every possible combination of inputs. Truth Tables for AND, OR and NOT :
P
Q
P && Q
true
true
true
true
false
false
false
true
false
false
false
false
P
Q
P || Q
true
true
true
true
false
true
false
true
true
false
false
false
P
!P
true
false
false
true
DeMorgan's Laws:
NOT(P AND Q) is equivalent to (NOT P) OR (NOT Q)
!(P && Q) = (!P) || (!Q)
NOT(P OR Q) is equivalent to (NOT P) AND (NOT Q)
!(P || Q) = (!P) && (!Q)
Examples:
Expression
Equivalent Expression
!(P == Q)
P != Q
!(P == Q | | P == R)
P != Q && P != R
!(P == Q && P == R)
P != Q | | P != R
!(P == Q && R > S)
P !=Q | | R <=S
Note: The expression on the left it's just the one to its right with ! added and the relational and logical operators reversed (Ex: = = instead of !=, | | instead of &&, <= instead of >). It is useful when rewriting expressions in simpler forms.
Example:
5 * 7 >= 3 + 5 * (7 - 1)
5 * 7 >= 3 + 5 * 6
35 >= 3 + 30
35 >= 33
trueMore Examples:
10 > 8 && 12 > 25 false
10 > 8 | | 12 > 25 true
!(10 > 8) false
!(hours > 40) same as: hours <= 40 false (where hours = 52)
mid_grade == 'A' || final_grade == 'A' true (if final_grade is 'A')4. Compound Logical Expressions: Relational operators cannot be "chained" as they can in algebra. In Java it is illegal to use more than one relational operator in a single comparison as is often done in mathematics.
Example://Assume: int x = 5;
EXPRESSION:2 <= x <= 10 // Expression evaluated from left to right:
true <= 10 // Error! Cannot compare a boolean with an int
- To express the idea embodied in the mathematical expression 0 <= x <= 9 you need to make both comparisons explicit, as in 0 <= x && x <= 9
- At this stage, the most common errors are those resulting from improperly formed expressions. You may try to put logical expressions into the serial form used in English conjunctive expressions. This results in incorrect expressions of the form x, y, z && q. You may try to write relational expressions such as a < b < c. ==> You just wrote incorrect logical expressions!
- Should learn to evaluate logical expressions and to carefully test each logical expression during the design phase.
5. Short-Circuit Evaluation: Java uses short-circuit evaluation of logical expressions, which means that logical expressions are evaluated left to right and evaluation stops as soon as the final truth value is known. In other words, evaluation proceeds from left to right and Java stops evaluating subexpressions as soon as the truth value of the entire expression can be determined (looking at all subexpressions would be a waste of time). When Java sees a && operator or a ||, the expression on the left side of the operator is evaluated first.
Rule of thumb:
- Found first true in OR --> The entire expression is true
- Found first false in AND --> The entire expression is false
Example:
boolean a, b, c;
a = !(5 > 2); // a is false
b = !(2 > 5); // b is true
c = a && b; // c is falseWhen Java evaluates the expression c = a && b;, it first checks whether a is true. Here a is false, so a && b must be false regardless of whether b is or is not true, so Java doesn't bother checking the value of b. On the other hand when faced with an || Java short circuits the evaluation as soon as it encounters a true value since the resulting expression must be true. This short circuit evaluation is less important in Java than in C or C++ because in Java the operands of && and || must be booleans which are unlikely to have side effects that depend on whether or not they are evaluated.
Example 1:int a = 25;
int b = 150;EXPRESSION:(a > 50) && (b > 140) // false
Evaluation can stop early becausethe result of && is only true when both sides are true. After determining that (a > 50) is false, it is already determined that the entire expression will be false.Example 2:
int a = 25;
int b = 150;EXPRESSION:(b >= 150)||(a > 40) // true
Evaluation can stop early because the result of || (OR) is true when one side is true. After determining that (b >= 150) is true, it is already determined that the entire expression will be true.Example 3:
int a = 25;
int b = 150;EXPRESSION:(a < 50) && (b > 140) // true
The second side must be evaluated because the result is true only if both of them are true. After determining that (a < 50) is true, we have to determine the truth value of the second part.Example 4:
int a = 25;
int b = 150;EXPRESSION:!(a > 20) || (b < 140) // false
The second side must be evaluated because the result is true if one side is true. After determining that (a > 20) is true, it follows that!(a > 20) is false and we have to determine the truth value of the second part.Write an expression for the following:
- taxRate is over 25% and income is less than $20000
- temperature is less than or equal to 75 or humidity is less than 70%
- age is over 21 and age is less than 60
- age is 21 or 22
6. Precedence of Operators:Relational operators have lower precedence than arithmetic operators. Logical opreators have lower precedence than both relational and arithmetic operators. Finally let's add the relational and logical operators to the precedence table shown in Lecture #3.
|
|||
Operator |
Meaning |
Associativity |
Precedence |
! |
NOT |
(right-to-left) |
Highest |
*, /, % |
Multiplication,
Division, Modulus |
(left-to-right) |
| |
+, - |
Addition,
Subtraction |
(left-to-right) |
| |
< |
Less than |
(left-to-right) |
| |
<= |
Less than or equal to |
(left-to-right) |
| |
> |
Greater than |
(left-to-right) |
| |
>= |
Greater than or equal
to |
(left-to-right) |
| |
== |
Is equal to |
(left-to-right) |
| |
!= |
Is not equal to |
(left-to-right) |
| |
&& |
AND |
(left-to-right) |
| |
|| |
OR |
(left-to-right) |
V |
= |
Assignment |
(right-to-left) |
Lowest |
7. Comaparing Strings in Java:
Example1:
String str1 = "Small";
str1.compareTo("Small");
// 0
str1.compareTo("Tree"); //
Negative number - 'S' comes before 'T'
str1.compareTo("Smile"); //
Negative number - 'a' comes before 'i'
str1.compareTo("Mall"); //
Positive number - 'S' comes after 'M'
Example2:
String str1 = "Small";
boolean
same;
same =
str1.equals("Small"); // true
same = str1.equals("Smile"); // false
The IF Statement: fundamental control structure that allows branches in the
flow of control. If a certain condition exists, then do something; else, do
something else. The if
statement comes in 2 forms in Java: the IF-THEN-ELSE form and the IF-THEN form.
a) The IF-THEN-ELSE Form
(2-way selection)
if
(Expression) // also called decision maker
StatementA // also called action statement
else
StatementB // also called action statement
Note: StatementA and StatementB each can be a single
statement, a null statement, or a block.
if
(Expression){
// if clause (or
then clause)
}
else {
// else clause
}
Note 1: Braces can only be omitted when each clause is a single
statement!
Note 1: The
else statement has to be paired with an if statement.
Note 3: Sometimes programmers forget
to put braces around a compound if-clause or else-clause. The error is not
readily apparent during a visual debugging because indentation makes the code
appear to be correct:
if (a <
b)
c = d;
e = f;
g = h;
In this example, the assignment e = f is always
executed because it is not part of the if statement. Some programmers surround every if-clause and else-clause with braces, even if
the clause has only one statement.
Note 4: Because most statements are
short enough to fit on a single line, you may get into the habit of ending each
line with a semicolon. You may not realize that by putting a semicolon at the
end of theif
heading or the end of the word else, you are turning the if-clause or the else-clause into a null
statement. For example, the code
if (a <
b);
c = d;
e = f;
g = h;
has an emptyif-clause (does nothing), and the
three assignment statements are always executed. This is another example of an
error that is hard to spot during a visual debugging.
Note 5: A matter of style - Indent only
the if-clauses
and else-clauses,
not the entire if statement.
Note 6: Never use a semicolon after
the right braces! Semicolons are used only to terminate simple statements
(assignment statements, input statements, and output statements)
Note 7: Do not use = (assignment
operator) instead of = = (relational equality operator) when testing for
equality.
if ((carDoors == 4 ) && (driverAge > 24))
premium = 650.0;
System.out.println("
LOW RISK! ");
else
premium = 1200.0;
System.out.println("
HIGH RISK! ");
monthlyPayment = premium /12.0;
Compile error! The
"if
clause" is the single statement following if (i.e. premium = 650.00)
==> dangling else!
Fix it.
if (purchase > 100.00) {
discountRate
= .25;
shipCost
= 10.0;
}
else {
discountRate
= .15;
shipCost
= 5.0;
}
totalBill
= purchase * (1.0 - discountRate) + shipCost;
System.out.println("Total
payment = " + totalBill);
if (score >= 70)
grade = 'P';
else
grade = 'F';
System.out.println("
Grade = " + grade);
if ( n >= 0 )
System.out.println(n
+ " is not negative");
else {
System.out.println(n
+ " is negative. Will make it positive!");
n = -n;
}
Scanner input = new Scanner(System.in);
int
n;
System.out.print("
Enter a number: ");
n = input.nextInt();
if (n = 5)// n = 5 is not a
logical expression. Need to replace = with ==
System.out.println(n
+ " is 5");
else
System.out.println(n
+ " is NOT 5");
/*SAMPLE OUTPUT:
1 error found:
File: C:\home\IZ\TestAssignment.java
[line: 12]
Error: C:\home\IZ\TestAssignment.java:12:
incompatible types
found : int
required: boolean */
if (hours > 40.0)
wages = 40.0 * pay_rate + 1.5 * pay_rate *
(hours - 40.0);
else
wages = hours * pay_rate;
b) The IF-THEN Form(one-way
selection)-
the else-clause is empty. It is a
selection of whether or not to execute a statement (which can be a single
statement, a null statement, or an entire block)
if
(Expression) {
statement(s)
}
// make sure x
is positive
if (x < 0) {
x = -x;
}
// otherwise,
continue from here
//Correct the logical errors:
if (temp < 32 )
System.out.println("Freezing!
Stay home.");
System.out.println("Decent
temperature! Go out.");
System.out.println("The
temperature is " + temp);
|
|
MIN |
MAX |
int min; |
int max; |
int min = Math.min(x, y); |
int max = Math.max(x, y); |
Nested IF
Statements -
The body of anif-clause or else-clause can contain another ifor
if-else
statement (this is called a nested control structure or a nested if). Actually, you can have an if within an if, within an if The only limitation is the
readability of the program.
|
|
Sequential if Diagram |
Nested if Diagram |
if (<test1>) { |
if (<test1>) { |
Version 1: separate if
statements
import java.util.Scanner;
class
WeekDay1 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int day;
System.out.print("Enter the number of the day:
");
day = input.nextInt();
if(day == 1) System.out.println("Sunday");
if(day == 2) System.out.println("Monday");
if(day == 3) System.out.println("Tuesday");
if(day == 4) System.out.println("Wednesday");
if(day == 5) System.out.println("Thursday");
if(day == 6) System.out.println("Friday");
if(day == 7) System.out.println("Saturday");
if (day < 1 || day > 7)
{
System.out.println("Error - unexpected value for
day!");
System.out.println("Should be between 1 and 7.");
System.out.println("You entered: " + day +
"\n");
}
}
}
Note: The value of day must be checked at every if, whether or not the day has been matched and printed. Also, a complex test is necessary to handle an error and print the error message.
Version 2: nested if statements
import java.util.Scanner;
class
WeekDay2 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int day;
System.out.print("Enter the number of the day:
");
day = input.nextInt();
if(day == 1) System.out.println("Sunday");
else
if(day == 2) System.out.println("Monday");
else
if(day == 3) System.out.println("Tuesday");
else
if(day == 4) System.out.println("Wednesday");
else
if(day == 5) System.out.println("Thursday");
else
if(day == 6) System.out.println("Friday");
else
if(day == 7) System.out.println("Saturday");
else
{
System.out.println("Error - unexpected value for
day!");
System.out.println("Should be between 1 and
7.");
System.out.println("You entered: " + day +
"\n");
}
}
}
Note 1:
The value of day
must be checked at every if
until a match is found. The other if statementswill be skipped.
Note 2: Only an else-clause is needed
to handle an error and print the error message.
Note 3: A matter of style: You can
see how in the second version, using nested if statements, the indentation moves
continually to right. You can use a special indentation style with deeply
nested if-then-else
statements (to indicate that you choose one alternative from a set of alternatives).
This style is known as if-then-else-if.
Version 3: if-then-else-if
import java.util.Scanner;
class
WeekDay3 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int day;
System.out.print("Enter the number of the day:
");
day = input.nextInt();
if(day == 1) System.out.println("Sunday");
else if(day == 2) System.out.println("Monday");
else if(day == 3) System.out.println("Tuesday");
else if(day == 4) System.out.println("Wednesday");
else if(day == 5) System.out.println("Thursday");
else if(day == 6) System.out.println("Friday");
else if(day == 7) System.out.println("Saturday");
else
{
System.out.println("Error - unexpected value for
day!");
System.out.println("Should be between 1 and
7.");
System.out.println("You entered: " + day +
"\n");
}
}
}
Conclusion: Nested if statements are
more efficient than separate if
statements - fewer comparisons.
Example 10:
|
|
// assign a grade -
incorrect version
|
// assign a grade -
corrected version
|
Example 11:
//Explain the difference between the statements below.
//For each of them, what is the final value of x
//if the initial value is 0?
if(x >= 0)
x = x + 1;
else if(x >= 1)
x = x + 2;if(x >= 0)
x = x + 1;
if(x >= 1)
x = x + 2;Example 12:
//Explain the difference between the statements below.
//What value is assigned to fee when speed has the value 85?
if(speed > 35)
fee = 20;
else if(speed > 50)
fee = 40;
else if(speed > 75)
fee = 60;if(speed > 75)
fee = 60;
else if(speed > 50)
fee = 40;
else if(speed > 35)
fee = 20;Example 13: What is wrong here, if anything?
if(score >= 60)
grade = 'D';
else if(score >= 70)
grade = 'C';
else if(score >= 80)
grade = 'B';
else if(score >= 90)
grade = 'A';
else
grade = 'F';
System.out.println("The grade is: " + grade);Example 14: What does the following statement print? (All variables are of type int.)
if (j < k)
if (k < j)
System.out.println("1");
else
System.out.println("2");
else
if (j < k)
System.out.println("3");
else
System.out.println("4");
a. It prints nothing unless j equals k.
b. It always prints 4.
c. It prints 2 if j equals k and 4 otherwise.
d. It prints 2 if j < k and 1 if k <= j.
e. It prints 2 if j <k and 4 otherwise.
The switch statement provides a convenient syntax for choosing among a set of possible paths. switch = a selection control structure for multi-way branching.
switch (IntegralExpression){
case Constant1:
Statement(s); // optional
case Constant2:
Statement(s); // optional
.
.
.
default:
// optional
Statement(s);// optional
}
1. Evaluate IntegralExpression
(also called control expression or selector) - can be an
identifier
2. Compare the value in IntegralExpression
to the constants in the case labels. The constants can
only be integral.
3. If match is found, execute statements following label
4. Continue execution until break or end of switch body found
5. If no match is found - then execute the statements under default.
//using printf to better control the
output
import java.util.Scanner;
class
Transformations_2 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
double weightInPounds = 295.6 ;
char weightUnit;
System.out.print("Enter letter for desired
weight unit: ");
weightUnit = input.next().charAt(0);
switch(weightUnit) {
case 'P':
case 'p':
System.out.printf("The weight in puonds = %10.3f\n", weightInPounds);
break;
case 'O':
case 'o':
System.out.printf("The weight in ounces =
%10.3f\n", 16 * weightInPounds);
break;
case 'K':
case 'k':
System.out.printf("The weight in kilos =
%10.3f\n", weightInPounds / 2.2);
break;
case 'G':
case 'g':
System.out.printf("The weight in grams =
%10.3f\n", 454.0 * weightInPounds);
break;
default:
System.out.println("That unit is not handled!
Invalid input.");
break;
}//close switch
}//close main()
} //close class
SAMPLE OUTPUT:
FIRST RUN:
Enter letter for
desired weight unit: m
That unit is not
handled! Invalid input.
SECOND RUN:
Enter letter for
desired weight unit: g
The weight in grams =
134202.400
THIRD RUN:
Enter letter for
desired weight unit: k
The weight in kilos
= 134.364
FOURTH RUN:
Enter letter for
desired weight unit: o
The weight in ounces
= 4729.600
|
|
SOLUTION #1 (default clause in switch) |
SOLUTION #2 (input control) |
import java.util.Scanner; |
import java.util.Scanner; |
In addition to the if and switch statements, Java provides a more compact way to express conditional execution that can be extremely useful in certain situations. This feature is called the ?: operator (pronounced question-mark-colon) and it has the following form (syntax):
Condition
? Expression1 : Expression2
int
x, y, min;
min = ( x < y ) ? x
: y;
System.out.println("The
smallest value is: " + min);
|
|
MIN |
MAX |
int min; |
int max; |
int min = Math.min(x, y); |
int max = Math.max(x, y); |
int min = (x < y)? x: y; |
int max = (x > y)? x: y; |
Program #1
//******************************************************************
// This
program determines (1) a student's average based on three
// test
scores and (2) the student's passing/failing status
//******************************************************************
import java.util.Scanner;
class Grades {
public static void main(String[] args){
//Declarations
Scanner input = new Scanner(System.in);
double average; // Average of
three test scores
int studentID;
// Student's identification number
int
test1; //
Score for first test
int
test2; //
Score for second test
int
test3; //
Score for third test
boolean dataOK;
// True if data is correct
//Get data
System.out.print("Enter a Student ID number and
three test scores: ");
studentID = input.nextInt();
test1 = input.nextInt();
test2 = input.nextInt();
test3 = input.nextInt();
System.out.println("\nStudent
number: " + studentID);
System.out.println("Test Scores: " + test1
+ ", " + test2 + ", " + test3);
//Test data for valid input
if (test1 < 0 || test2 < 0 || test3 < 0)
dataOK = false;
else
dataOK = true;
if (dataOK) {
//Calculate average
average = (double)(test1 + test2 + test3) / 3.0;
//Print message
System.out.printf("Average score is " +
"%5.2f", average);
if (average >= 60.0){
System.out.print(" --- Passing "); //Student is passing
if (average < 70.0)
System.out.print(" but marginal"); //But marginal
System.out.print(".\n");
}
else //Student is failing
System.out.println(" --- Failing.");
}
else //Invalid data error message
System.out.println("Invalid Data: Score(s) less
than zero.");
}//close main()
}//close class
SAMPLE
OUTPUT:
FIRST RUN:
Enter a
Student ID number and three test scores: 12345 89 78 95
Student
number: 12345
Test
Scores: 89, 78, 95
Average
score is 87.33 --- Passing .
SECOND
RUN:
Enter a
Student ID number and three test scores: 12346 71 65 69
Student
number: 12346
Test
Scores: 71, 65, 69
Average
score is 68.33 --- Passing but marginal.
THIRD RUN:
Enter a
Student ID number and three test scores: 123457 54 36 50
Student
number: 123457
Test
Scores: 54, 36, 50
Average
score is 46.67 --- Failing.
Program #2
import java.util.Scanner;
class DaysMonth {
public static void main(String[] args){
//Declarations
Scanner input = new Scanner(System.in);
int month;
//Get data
System.out.print("Enter a number for month (Jan
= 1): ");
month = input.nextInt();
switch (month) {
case 2:
System.out.println("28 days (29 in leap
years.)");
break;
case 4:
case 6:
case 9:
case 11:
System.out.println("30 days.");
break;
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
System.out.println("31 days.");
break;
default:
System.out.println("Illegal month
number.");
break;
}//close switch
}//close main()
}//close class
SAMPLE
OUTPUT:
FIRST RUN:
Enter a
number for month (Jan = 1): 16
Illegal
month number.
SECOND
RUN:
Enter a
number for month (Jan = 1): 3
31 days.
THIRD RUN:
Enter a
number for month (Jan = 1): 9
30 days.
FOURTH
RUN:
Enter a
number for month (Jan = 1): 2
28 days
(29 in leap years.)
Additional
Resources:
1. (Oracle) The Java Tutorials: Equality, Relational, and Conditional Operators http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
2. (Oracle) The Java Tutorials: The if-then and if-then-else Statements
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html
3. (Oracle) The Java Tutorials: The switch Statement http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
References:
[1] Building Java Programs: A Back to Basics Approach, by Stuart Reges, and Marty Stepp, Addison
Wesley, 2008.
[2] Java Programming: From Problem Analysis to Program Design, by D.S. Malik,
Thomson Course Technology, 2008