if-else
In today's lecture we discuss the concept of variable scope
and how it impacts statements that have blocks of code
(like if
). We also look at a more general form
of the if
statement, as well as more general
boolean expressions.
Succeed in Science (you should register if you plan on attending).
Midterm labtests from last year will be posted (see the main course website).
Regular office hours (3:30—5:00pm Wed and Thurs).
if
if (logical-expression) { statement(s) }
The if
statement lets you divert program flow based
on a
logical-expression;
if the expression
is true
then program flow goes to the block of
statements.
Pairs of braces { }
denote blocks of code.
A variable declared inside a block is usable everywhere after the
declaration inside the block. Consider our template code for example:
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample1
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
}
}
The reference variables output
and input
are usable everywhere inside the block of black braces (everywhere
after they have been declared that is)
Outside of the block of black braces, however, the reference
variables output
and input
cannot be
used. We say that the black braces
denote the scope of the variables output
and
input
.
Suppose we add a block of code inside the main
method
after the declarations of output
and input
:
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample1
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
{
output.print(userValue);
}
}
}
Inside the purple block, we are allowed to use the variables
output
and userValue
because we are
inside of their scope (between the black braces after the variables
were declared).
We can also declare variables inside of the purple block.
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample1
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
{
output.print(userValue);
float absValue = Math.abs(userValue);
output.printf(" and its absolute value %f%n", absValue);
}
}
}
The variable absValue
is local to the purple block
because it can only be used inside of the purple block (the scope
of absValue
is the purple block). Trying to use
absValue
outside of its scope will result in a
compilation error:
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample1
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
{
output.print(userValue);
float absValue = Math.abs(userValue);
output.printf(" and its absolute value %f%n", absValue);
}
// error! absValue is out of scope
float signum = userValue / absValue;
}
}
One way to fix the compilation error on the previous slide
is to declare a second variable named absValue
after the purple block:
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample1
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
{
output.print(userValue);
float absValue = Math.abs(userValue);
output.printf(" and its absolute value %f%n", absValue);
}
float absValue = Math.abs(userValue);
float signum = userValue / absValue;
}
}
In this example, it looks like we are re-declaring a variable
named absValue
, which should be illegal. What is
actually happening is that we are declaring absValue
for the first time in the black block; thus, the declaration
is legal.
A second solution would be to declare absValue
before the purple block:
import java.io.PrintStream;
import java.util.Scanner;
public class BlockExample2
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
float absValue;
{
output.print(userValue);
absValue = Math.abs(userValue);
output.printf(" and its absolute value %f%n", absValue);
}
float signum = userValue / absValue;
}
}
In this example, declaring a local variable in the purple
block named absValue
would have been illegal because
absValue
was declared earlier in the black block
(the enclosing scope).
int speed = 100; { speed = 25 { double speed = 250.0; } speed = 15.0; { speed = 1; { speed = 2; } } } speed = 150;
char grade = 'B'; System.out.print(grade); { System.out.print(grade); { grade = 'C'; System.out.print(grade); } System.out.print(grade); } System.out.print(grade);
Because the if
statement injects a block into
your code.
public class BlockExample3
{
public static void main(String[] args)
{
PrintStream output = System.out;
Scanner input = new Scanner(System.in);
float userValue = input.nextFloat();
if (userValue < 0f)
{
float absValue = -userValue;
}
// error! absValue is out of scope
float signum = userValue / absValue;
}
}
To fix the above example, you need to move the declaration of
absValue
outside and before the if
statement.
float absValue = userValue; if (userValue < 0f) { absValue = -userValue; }
if-else
An if-else
statement diverts program flow into two
separate blocks.
if (logical-expression) { statement(s) } else { statement(s) }
If the logical-expression is true then program flow goes to the purple block; otherwise program flow goes to the orange block.
In Ontario, most hourly employees earn overtime pay after they have worked 44 hours in a work week. Overtime time is 150% of the employee's regular rate of pay. Write a program that calculates an employee's total pay based on a user-input number of hours worked in the week and the regular hourly wage. Your program should output both the regular-time pay and the overtime pay.
1. ask for the number of hours worked 2. get the number of hours worked 3. ask for the regular hourly wage 4. get the regular hourly wage 5. if the number of hours worked > 44 regular pay = 44 * hour wage overtime pay = (number of hours worked - 44) * hourly wage * 1.5 else regular pay = number of hours worked * hourly wage overtime pay = 0 6. output the result
Below we show only the implementation of Step 5.
final double FULL_WEEK = 44.0; final double OVERTIME_RATE = 1.5; double regularPay; double overtimePay; if (hours > FULL_WEEK) { regularPay = FULL_WEEK * hourlyWage; overtimePay = (hours - FULL_WEEK) * hourlyWage * OVERTIME_RATE; } else { regularPay = hours * hourlyWage; overtimePay = 0.0; }
Why are the variables regularPay
and
overtimePay
declared before the if-else
statement?
Can you rewrite Step 5 using only an if
statement?
When you need to divert program flow to more than two paths
of execution you use the if-else
statement
with a second if-else
statement going in
each else
block.
import java.io.PrintStream; import java.util.Scanner; import type.lib.ToolBox; public class LetterGrade { public static void main(String[] args) { PrintStream output = System.out; Scanner input = new Scanner(System.in); output.print("Enter your numeric grade : "); int grade = input.nextInt(); ToolBox.crash(grade < 0, "Grade is less than 0"); ToolBox.crash(grade > 100, "Grade is greater than 100"); final int GRADE_E = 40; final int GRADE_D = 50; final int GRADE_DP = 55; final int GRADE_C = 60; final int GRADE_CP = 65; final int GRADE_B = 70; final int GRADE_BP = 75; final int GRADE_A = 80; final int GRADE_AP = 90; if (grade < GRADE_E) { output.println("F"); } else if (grade < GRADE_D) { output.println("E"); } else if (grade < GRADE_DP) { output.println("D"); } else if (grade < GRADE_C) { output.println("D+"); } else if (grade < GRADE_CP) { output.println("C"); } else if (grade < GRADE_B) { output.println("C+"); } else if (grade < GRADE_BP) { output.println("B"); } else if (grade < GRADE_A) { output.println("B+"); } else if (grade < GRADE_AP) { output.println("A"); } else { output.println("A+"); } } }
Suppose you were writing a program where you needed to find
the minimum of three unique real numbers stored in variables
eig1
, eig2
, and eig3
.
if (eig1 is less than eig2) AND (eig1 is less than eig3) min = eig1 else if (eig2 is less than eig1) AND (eig2 is less than eig3) min = eig2 else min = eig3
If a condition depends on two expressions being true
you
would use the Conditional-AND operator &&
to combine the two expressions:
if ((eig1 < eig2) && (eig1 < eig3)) { min = eig1; } else if ((eig2 < eig1) && (eig2 < eig3)) { min = eig2; } else { min = eig3; }
Java evaluates the boolean expressions from left to right. For
Conditional-AND, if the boolean expression on the left hand side is
false
, Java does not evaluate the boolean expression
on the right hand side.
If a condition depends either of two expressions being true
you would use the Conditional-OR operator ||
(two vertical bars) to combine the two expressions.
For example, suppose you are the quality control engineer at a food packaging plant. Your packaging machine is supposed to fill packages with a certain weight of product, and you need to reject packages that are too light or too heavy.
if (weight < target weight) OR (weight > target weight) reject package
final double TARGET_WEIGHT = 500; if ((weight < TARGET_WEIGHT) || (weight > TARGET_WEIGHT)) { output.println("Rejected!"); }
Java evaluates the boolean expressions from left to right. For
Conditional-OR, if the boolean expression on the left hand side is
true
, Java does not evaluate the boolean expression
on the right hand side.