A decision structure is a construct in a computer program that allows the program to make a decision and change its behavior based on that decision. The decision is made based on the outcome of a logical test. A logical test is a calculation whose outcome is either true or false.
In today's lecture I will introduce two simple decision structures, the if statement and the switch statement.
The if statement is the simplest example of a decision structure in Java. In an if statement a logical test is made which can evaluate to either true or false. If the result of the test is true, the statements in the if branch are executed. If the result of the test is false, the statements in the else branch are executed. Once the statements in the appropriate branch have been executed, the flow of execution continues on to the statements that follow the if statement.
Here is a simple example. Below is the code for program that computes and prints the absolute value of a number the user inputs.
public class AbsValue {
public static void main(String[] args) {
int x, absX;
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer x: ");
x = input.nextInt();
// if statement starts below
if (x < 0) {
// This is the if branch
absX = -x;
} else {
// This is the else branch
absX = x;
}
System.out.println("The absolute value of " + x + " is " + absX);
}
}
The test in the if statement is a simple comparison test that checks whether or not the value stored in x is positive. If the test evaluates to true, the code following the test is executed. If the test evaluates to false, the code following the else is executed instead. Note that curly braces are used to delimit the two branches.
The exact placement of the curly braces is a matter of taste. Each of the following forms is legal:
if(x < 0)
{
absX = -x;
}
else
{
absX = x;
}
if(x < 0) { absX = -x; }
else { absX = x; }
In cases where the body of one of the branches of the if statement reduces to just a single statement, the curly braces are optional.
if(x < 0) absX = -x; else absX = x;
The else branch is also optional. In cases where the logic requires only that something be done when a particular condition applies, only the if branch may be necessary. For example, we can write the program above this way.
public class AbsValue2 {
public static void main(String[] args) {
int x, absX;
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer x: ");
x = input.nextInt();
absX = x;
if (x < 0)
absX = -x;
System.out.println("The absolute value of " + x + " is " + absX);
}
}
The next few example programs we are going to see are all programs that do numerical calculations. In numerical programs, most decisions are made on the basis of numerical comparisons. The table below shows the comparison operators available for use in Java.
| Operator | Meaning |
|---|---|
| == | is equal to |
| != | is not equal to |
| < | is less than |
| <= | is less than or equal to |
| > | is greater than |
| >= | is greater than or equal to |
Important warning: note that the comparison operator for equality is ==, not =. This leads to one of the more common mistakes that beginning Java programmers make. The follow code is legal, but does not do what you might expect.
if(n = 10) n = 0;
What happens in this case is that rather than testing whether or not n equals 10, the code in the test actually sets n equal to 10. (After that the code in the if branch gets executed anyway, regardless of the original value of n.)
An if statement gives us the ability to ask a single question and do something in response to that question. Often, the logic of a particular situation will dictate that we ask more than one question to resolve a situation. In that case, we may need to make use of a nested if. The following example demonstrates how this works in practice. The program below has the user enter three floating point numbers that form the coefficients of a polynomial p(x) = a x2 + b x + c. The program will then try to determine what the roots of that polynomial are and print the roots.
The key decision that has to be made is based on the value of the descriminant, b2 - 4 a c. If that quantity is negative, the polynomial has no real roots. If it 0, the equation has one real root, and if it is greater than 0 there are two distinct real roots. The program below uses a pair of nested if statements to determine which of these three cases we are dealing with.
public class PolynomialRoots {
public static void main(String[] args) {
double a,b,c,desc;
Scanner input = new Scanner(System.in);
System.out.print("Enter the coefficients a, b, and c: ");
a = input.nextDouble();
b = input.nextDouble();
c = input.nextDouble();
desc = b*b - 4*a*c;
if(desc < 0.0) {
// First case - no real roots
System.out.println("The polynomial has no real roots.");
}
else {
// Second case - one or two real roots
if(desc == 0.0){
double root = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has one root, " + root);
}
else {
double root1 = (-b-Math.sqrt(desc))/(2*a);
double root2 = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has two roots, "
+ root1 + " and " + root2);
}
}
}
}
The first if test distinguishes between the case where there are no real roots and the case where there are real roots. Within the second case we have to ask a further question to determine if there is a repeated real root or two distinct real roots. We do this by simply placing a second if statement inside the else part of the first if statement.
The example above is an example of a categorization task. The answer we are looking for can fall into one of three categories, so we ask a couple of questions to determine which of the three categories we have. Note that to accomplish the categorization we have to nest the if statement that asks the second question inside the else part of the if statement that asks the first question.
Since an entire if-else construct is considered to be a single compound statement in Java, we can take advantage of the special rule that says that if the if or else part of an if-else statement reduces to just a single term we can eliminate the curly braces. Deploying that rule converts the structure of the code to something like this:
if(desc < 0.0) {
System.out.println("The polynomial has no real roots.");
}
else
if(desc == 0.0){
double root = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has one root, " + root);
}
else {
double root1 = (-b-Math.sqrt(desc))/(2*a);
double root2 = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has two roots, "
+ root1 + " and " + root2);
}
Eliminating the line break between the else and if and modifying the structure slightly produces this form.
if(desc < 0.0) {
System.out.println("The polynomial has no real roots.");
}
else if(desc == 0.0){
double root = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has one root, " + root);
} else {
double root1 = (-b-Math.sqrt(desc))/(2*a);
double root2 = (-b+Math.sqrt(desc))/(2*a);
System.out.println("The polynomial has two roots, "
+ root1 + " and " + root2);
}
The resulting form is identical syntactically and functionally to the nested-if form we started with above. This so-called chained if-else form is very useful for categorization. Using this form we can ask a series of questions designed to determine which of several categories applies in a given situation.
Here is an example from the text. ComputeBMI.java computes a Body Mass Index in much the same way we did in an exercise in the first lab. To make that index more meaningful, the program also provides interpretation. There is a BMI scale that can be used to determine whether a person is seriously underweight, underweight, normal weight, overweight, or seriously overweight. The program uses a chained if-else construct to determine which of these five categories the user's BMI places them in.
public class ComputeBMI {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Prompt the user to enter weight in pounds
System.out.print("Enter weight in pounds: ");
double weight = input.nextDouble();
// Prompt the user to enter height in inches
System.out.print("Enter height in inches: ");
double height = input.nextDouble();
final double KILOGRAMS_PER_POUND = 0.45359237; // Constant
final double METERS_PER_INCH = 0.0254; // Constant
// Compute BMI
double bmi = weight * KILOGRAMS_PER_POUND /
((height * METERS_PER_INCH) * (height * METERS_PER_INCH));
// Display result
System.out.println("Your BMI is " + bmi);
if (bmi < 16)
System.out.println("You are seriously underweight");
else if (bmi < 18)
System.out.println("You are underweight");
else if (bmi < 24)
System.out.println("You are normal weight");
else if (bmi < 29)
System.out.println("You are overweight");
else if (bmi < 35)
System.out.println("You are seriously overweight");
else
System.out.println("You are gravely overweight");
}
}
Some questions we would like to ask can not be phrased readily as simple comparisons. To make it possible to form more complex tests, Java allows you to form compound tests by combining simple tests with logical operators. The table below shows the three logical operators that can be used to form compound tests.
| operator | interpretation |
|---|---|
| && | logical and |
| || | logical or |
| ! | logical negation |
Compound tests are formed in a fairly natural way by combining simple tests. For example, here is a compound test to determine whether or not the integer variable x falls in the range between 5 and 10, inclusive.
if((x >= 5)&&(x <= 10))
System.out.println("x falls in the range [5,10]");
Here is another example that uses a compound test. To determine whether or not a given year is a leap year, we have to use the following rules.
The test to determine whether or not a year is a leap year is best accomplished with a compound test, as this code shows:
if(((year % 4 == 0)&&(year % 100 != 0))||(year % 400 == 0))
System.out.println("The year " + year + " is a leap year");
else
System.out.println("The year " + year + " is not a leap year");
We saw above that you can use a chained if-else construct to determine which of several categories something falls in. A very common special case of this problem occurs when we have a limited number of categories that can be labeled by individual integer values. To handle that special case, Java offers a special decision structure called the switch statement. Here is an example of switch statement in use. The program below prompts the user to enter an integer in the range from 0 to 9, and then converts the integer they entered into its text equivalent. This is a categorization task that involves putting ourselves in one of 10 distinct categories that can be labeled by integer values.
public class IntToString {
public static void main(String[] args) {
int x;
String word;
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer between 0 and 9: ");
x = input.nextInt();
switch(x) {
case 0:
word = "zero";
break;
case 1:
word = "one";
break;
case 2:
word = "two";
break;
case 3:
word = "three";
break;
case 4:
word = "four";
break;
case 5:
word = "five";
break;
case 6:
word = "six";
break;
case 7:
word = "seven";
break;
case 8:
word = "eight";
break;
case 9:
word = "nine";
break;
default:
word = "invalid";
}
System.out.println("The integer you entered is " + word);
}
}
The switch statement begins with
switch(x)
where x is the value of the variable whose value we wish to categorize. The body of the switch statement consists of a series of cases. Each case has a case label ending with a :, some code to be executed when x falls into that case, and a break statement to mark the end of the case. At the end of the body of the switch statement we also have a default case that says what to do when none of the cases above apply.
Here are two short programming exercises for you to try. These exercises are not to be turned in. I will show my solution to these two exercises in class on Monday.
1. Here is some code from chapter 2 in the text for a program that determines how many dollars, quarters, dimes, nickels, and pennies are in a given dollar amount.
public class ComputeChange {
public static void main(String[] args) {
// Create a Scanner
Scanner input = new Scanner(System.in);
// Receive the amount
System.out.print(
"Enter an amount in double, for example 11.56: ");
double amount = input.nextDouble();
int remainingAmount = (int)(amount * 100);
// Find the number of one dollars
int numberOfOneDollars = remainingAmount / 100;
remainingAmount = remainingAmount % 100;
// Find the number of quarters in the remaining amount
int numberOfQuarters = remainingAmount / 25;
remainingAmount = remainingAmount % 25;
// Find the number of dimes in the remaining amount
int numberOfDimes = remainingAmount / 10;
remainingAmount = remainingAmount % 10;
// Find the number of nickels in the remaining amount
int numberOfNickels = remainingAmount / 5;
remainingAmount = remainingAmount % 5;
// Find the number of pennies in the remaining amount
int numberOfPennies = remainingAmount;
// Display results
String output = "Your amount " + amount + " consists of \n" +
"\t" + numberOfOneDollars + " dollars\n" +
"\t" + numberOfQuarters + " quarters\n" +
"\t" + numberOfDimes + " dimes\n" +
"\t" + numberOfNickels + " nickels\n" +
"\t" + numberOfPennies + " pennies";
System.out.println(output);
}
}
Modify this program to be more intelligent in how it prints out the result. If a given denomination does not appear in the result, don't print anything for that denomination. If the amount for a given denomination is 1, print the singular form of that denomination; otherwise, use the plural form. For example, given the input 11.87, your program should print
Your amount 11.87 consists of 11 dollars 3 quarters 1 dime 2 pennies
2. Write a program that prompts the user for the month and year and prints a message saying how many days are in that month. For example, on the input 3 2009 your program should print
There are 31 days in the month 3 2009.
On the input 2 2000 your program should print
There are 29 days in the month 2 2000.