5 Boolean Expressions and if Statements

AP Computer Science A Prep, 2024 - Rob Franek 2023

5 Boolean Expressions and if Statements
Part V: Content Review for the AP Computer Science A Exam

Now that we have some tools to make the computer accomplish a simple task, let’s discuss how to make our programs a little more…interesting.

When you wake up in the morning, some tasks occur automatically, while others may depend on a decision. For example, if your alarm clock sounds at 6:00 A.M.…wait, what if it doesn’t? If it sounds at 6:00 A.M., you proceed with your morning rituals; if it does not sound, you wake up late and have to speed up or change, your routine. When you sit down to eat your favorite breakfast cereal…none is left! Now what?

Most, if not all, of the actions we perform depend on decisions. These decisions affect whether or not we perform the actions or even how we perform the actions. Programs possess this exact ability to make decisions and react accordingly. In this way, the programmer can control the flow of the program.

THE if STATEMENT

If you read the above examples closely, you will literally find the word if as a pivotal word in your decisions of what actions to perform next. The reserved word if is a conditional statement used in Java when programmers want to control the flow of the programs—e.g., if they want Line 2 to occur ONLY if a condition in Line 1 is true. This is referred to as flow control.

The syntax of a simple if statement is

if (condition) statement;

Syntax statements in this book will be presented in pseudocode in order to illustrate the general form, and then further examples will be given. Pseudocode is not Java code that will compile, but it shows the format of the Java statements that we will write later.

Consider an instance when you are asking a parent whether you can go out to the mall with a friend on Friday night. The (classic) parent response usually looks something like this: If you clean your room, you can go to the mall on Friday.

In pseudocode, the parent’s response could be written as

if (you clean your room) go to the mall;

In this example, “you clean your room” is the condition of the if statement and “go to the mall” is the statement. The condition in an if statement must have a boolean result. Note that if you do clean your room (true), you will go to the mall; however, if you do not clean your room (false), you will not go to the mall. The if statement is written in this way; the programmer is now controlling the flow of the program. Thus, “go to the mall” will occur if the condition is true, but will be skipped if the condition is false. Another popular (pseudocode) way to write this statement is

if (you clean your room)

go to the mall;

This construction simply uses white space to make the code more readable. The AP Exam may present an if statement in either of these formats.

Let’s try a code example. Consider the following lines from a Java program:

int num1 = 4, num2 = 5;

if (num1 == num2)

System.out.print(“The numbers are the same.”);

Since we have an if statement, one of two possibilities can occur based on whether num1 has the same value as num2: (1) the program will display the string literal “The numbers are the same.” if the condition is true, or (2) the program will not display any output if the condition is false.

Note the use, here, of the boolean operator == (also known as the equality operator); do not confuse this boolean operator with the assignment operator =. A boolean operator asks a question, while an assignment operator executes a command. num1 = 4 assigns the value 4 to the variable num1, while num1 == num2 determines whether the two values are equal. The assignment statement produces no other result, while the boolean statement returns a truth value based on the comparison.

Wouldn’t it be nice if conditions in life depended on just one comparison, as our previous code example did? If we dig a bit deeper into our alarm clock example from before, there are probably a few more decisions that need to be made in order to begin your morning rituals; a few of these decisions might be, “is it a school day?”…“do I feel healthy?”…“is my blanket glued to my mattress, trapping me between them?” Note that each of these questions, regardless of its plausibility, has a true or false (boolean) answer.

If (see how many times we use this word?) we want to incorporate a more complicated condition into our code, we must create a compound condition. Compound conditions include at least one boolean operator; all of these and their meanings are as follows:

&& logical and

|| logical or

! logical not

== is equal to

!= is not equal to

Let’s explore how each of these can be incorporated into a program.

Consider a situation in which you need a study break and decide to visit your local bakery for a snack. Your favorite dessert is typically Italian cannoli, but you will also accept an apple turnover. But apple turnovers are somewhat dry, so you will buy one only if they are selling coffee that day.

Since this example is relatively complicated, let’s break it into chunks.

When attacking a complicated programming situation, break it into chunks and tackle each part, one by one.

We will use pseudocode for this example.

Let’s outline the conditions presented in this example, in order:

· The bakery has cannoli.

· The bakery has apple turnovers.

· The bakery has coffee.

The complication here is that some of these decisions depend on others. For example, if the bakery DOES have cannoli, then it doesn’t matter whether it has apple turnovers. Again, step by step: start with condition (1).

if (bakery has cannoli) buy dessert;

Now, another decision must be made based on this decision; if the bakery DOES have cannoli, we get our desired dessert. If it does NOT have cannoli, we must try the apple turnover.

if (bakery has cannoli)

buy dessert; // occurs only if bakery has cannoli

else if (bakery has apple turnovers) // occurs only if bakery has no cannoli

buy dessert; // occurs only if bakery has apple turnovers

Note the else keyword used here. else is used if the programmer wants a statement to execute if the condition is false.

It’s not that easy, though…we must consider the coffee. Since you will buy an apple turnover only if there is ALSO coffee for sale, the && operator is appropriate here:

1 if (bakery has cannoli)

2 buy dessert; // bakery has cannoli

3 else if (bakery has apple turnovers && bakery has coffee) // no cannoli

4 buy dessert; // bakery has apple turnovers AND coffee

This pseudocode seems to work, but we must check for logical errors.

Using the numbered lines of pseudocode, let’s trace the possibilities using a trace table.

has cannoli: line 1, condition is true -> line 2, buy dessert

no cannoli, no turnovers, no coffee: line 1, false -> line 3, false -> no dessert

no cannoli, yes turnovers, no coffee: line 1, false -> line 3, false -> no dessert

no cannoli, no turnovers, yes coffee: line 1, false -> line 3, false -> no dessert

no cannoli, yes turnovers, yes coffee: line 1, false -> line 3, true -> line 4, buy dessert

Moral of the story: This bakery had better get itself together.

Image

Got a Question?

For answers to test-prep questions for all your tests and additional test-taking tips, subscribe to our YouTube channel at www.youtube.com/ThePrincetonReview

There is a lot of pseudocode here! Controlling the flow of a program can be difficult and confusing, which is why it is a popular topic on the AP Exam. But it is also important because most programs, like most things we do in life, rely on conditions and react accordingly.

If we look at the bakery example one more time, the line

buy dessert;

occurs twice. Good programming style attempts to repeat the same lines of code as little as possible, if ever. Therefore, we can rearrange the boolean operators in the following way, creating the same result:

if (bakery has cannoli OR (bakery has apple turnovers AND bakery has coffee))

buy dessert;

That is a hefty boolean condition; however, it (1) eliminates the repetition of code and (2) provides a more “elegant” programming solution. “Elegant” is a relative term, of course, but the AP Exam often uses this subjective term to write code and to confuse you. Either way, you should be familiar with both ways.

The AP Exam free-response questions do not require you to write code with “elegance”; in the free-response questions they will accept any code solution as long as it fulfills the specifications of the question.

To make things more complicated (or more life-like), consider a further idea. What if we want to execute several commands when a condition is true (or false) instead of just one? For example, using the bakery case, let’s say that buying cannoli is so exciting that we must devour it right away. In other words, if the conditions are met for the bakery having cannoli, we want to buy it AND eat it. The pseudocode would look something like:

1 if (bakery has cannoli)

2 {

3 buy dessert; // bakery has cannoli

4 eat dessert;

5 }

6 else if (bakery has apple turnovers && bakery has coffee) // no cannoli

7 buy dessert; // bakery has apple turnovers AND coffee

The {and} symbols in lines 2 and 5 indicate blocking, a technique used in flow control statements that allows the programmer to execute a series of commands (instead of just one) when a given condition is satisfied.

Use blocking to execute more than one statement based on a condition.

Here is a summary for evaluating boolean expressions:

· An && (and) expression is true if BOTH A and B are true.

· An || (or) expression is true if EITHER A or B is true, or if they are both true.

· The ! (not) operator simply reverses the truth value of the variable.

The truth value of an expression is often abbreviated to a single letter. Thus, A may represent an expression such as x >= 0. The expression will either be true or false depending on the value of x, but for simplicity’s sake we just refer to the whole expression as A.

Consider the following three expressions:

To evaluate A && B

First evaluate A. If A is false then stop: the whole expression is false. Since false && anything is false, there is no need to continue after the first false has been evaluated. This idea is called short-circuit evaluation. This idea is used (and tested) frequently. However, if A is true, then you must evaluate B to determine the truth value of the whole expression.

To evaluate A || B

First evaluate A. If A is true then stop: the whole expression is true. Since true || anything is true, there is no need to continue after the first true has been evaluated. This is short-circuit evaluation again. However, if A is false, then you must evaluate B to determine the truth value of the whole expression.

To evaluate !A

First evaluate A. If A is true, the whole expression is false. If A is false, the whole expression is true.

Image

1.Consider the following code.

int x = 0;

if (x == 0)

System.out.print(“1”);

else

System.out.print(“2”);

System.out.print(“3”);

Which of the following best describes the result of executing the code segment?

(A) Since the value of x is 0, the first print statement will be performed, producing 1 as the output.

(B) Since the value of x is 0, the first print statement will be performed, producing 13 as the output.

(C) Since the value of x is 0, the first print statement will be performed, producing 123 as the output.

(D) == is not the correct boolean operator, so a syntax error will be produced by the compiler prior to execution.

(E) == is not the correct boolean operator, so a logical error will be produced by the compiler prior to execution.

Here’s How to Crack It

Since x is assigned to 0, the condition of the if statement will be true, so the first print statement will be performed, and the output will be 1. The else statement will then be skipped, so 2 will not be outputted, eliminating (C). The trick here, however, is that the third print statement is NOT part of the else statement since it is not blocked with {}, even though it is (incorrectly) indented. This will output 3, eliminating (A). Furthermore, == is a valid boolean operator so (D) and (E) are clearly incorrect (and a compiler will never produce a logical error). The correct answer is (B).

Image

Image

2.Consider the following boolean expression.

(X && !Y) || (!X && Y)

Which of the following condition(s) will always cause the expression to evaluate to true?

(A) X is true

(B) Y is false

(C) X and Y are both true

(D) X and Y have the same truth values

(E) X and Y have opposite truth values

Here’s How to Crack It

The || indicates that either (X && !Y) is true or (!X && Y) is true. Each of these expressions uses a combination of X and Y, thus ruling out (A) and (B). In the first expression, X is true while Y is false. In the second expression, the reverse is true: Y is true and X is false. This eliminates both (C) and (D) because the truth values of X and Y cannot match and certainly cannot be both true. Since X and Y have opposite truth values, (E) is the correct answer.

Image

To sum up, let’s create a truth table of various combinations of boolean conditions, simply called A and B, and the truth possibilities based on those combinations. Since there are two variables, there are four possible combinations of their truth values: they are both true, only one of them is true (both ways), and neither is true. These possibilities are shown in the first two columns below. In subsequent columns, the truth values are shown for the boolean statements shown in the first row.

Image

Note that the truth values of the last two expressions are identical; these results are an illustration of DeMorgan’s Law, which might be thought of as the “distributive property” of boolean expressions. Applying a ! (not) operator to an expression reverses the truth value of each variable and changes an && to an ||, or vice versa. If this law is applied to !(A && B), the result is !A || !B, as shown in the last column.

The intricacies of if statements that we just explored will apply to all flow control statements, so understand them here before you move on to the next section.

Augustus De Morgan was a British mathematician and logician in the 19th century. De Morgan’s Law can be used to simplify complicated boolean expressions. The basic concept is to know that an expression can be rewritten to simplify and logically hold the same value. For example, logically speaking:

!true = false

!false = true

So the two forms of the law are stated as follows:

1.!(a && b) is equivalent to !a || !b

2.!(a || b) is equivalent to !a && !b

In other words, when you apply a negation to an expression inside parentheses, negate each expression and swap the operator.

Applying De Morgan’s Law:

Example 1

!(x >= 0 && y < 0)

First, handle the negation and swap && to ||

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

Now simplify each expression.

—If x is NOT >= 0 then it must be < 0

—If y is NOT < 0 then it must be >= 0

x < 0 || y >= 0

Example 2

!(x == 0 && !(y == 0))

First, handle the negation and swap && to ||

!(x == 0) || !!(y == 0)

Now simplify each expression.

—If x is NOT == 0 then it must be != 0

—Two negations eliminate each other

x != 0 || y == 0

Image

3.Consider the following code segment.

boolean a = true, b = false;

if (/ * missing code * /)

System.out.print(“Nice job.”);

else

System.out.print(“Nicer job.”);

Which of the following could be used to replace / * missing code * / so that the output of this block of code is “Nicer job.”?

   I. a && !b

II. !a || b

III. !a && b

(A) I only

(B) I and II only

(C) I and III only

(D) II and III only

(E) I, II, and III

Here’s How to Crack It

Ahh, the dreaded “Roman numeral” problems that the College Board loves to torture us with. If “Nicer job.” has to be displayed, then the condition must evaluate to false.

Roman numeral problems are only as annoying as their hardest option; look at the options and do the easiest one first, which is often not I. Then use Process of Elimination.

Create a truth table.

a

true

b

false

a && !b

true && false true && true true

!a || b

!true || false false || false false

!a && b

!true && false false && false false

Only the last two expressions result in a false outcome; thus (D) is the correct answer.

Image

Image

4.Suppose p and q are declared as boolean variables and have been initialized to unknown truth values.

What does the following boolean expression evaluate to?

(!p && !q) || !(p || q)

(A) The expression always evaluates to true.

(B) The expression always evaluates to false.

(C) The expression evaluates to true whenever p is false.

(D) The expression evaluates to true whenever q is false.

(E) The expression evaluates to false whenever p and q have opposite truth values.

Here’s How to Crack It

Using De Morgan’s Law, we can see that the truth value of the expression on the right, !(p || q), simplifies to the expression on the left, !p && !q. Since trial and error is a useful strategy, set up a truth table to evaluate the potential answers.

p

q

!p && !q

T

F

!T && !F

F && T

F

F

T

!F && !T

T && F

F

T

T

!T && !T

F && F

F

F

F

!F && !F

T && T

T

Eliminate (A) and (B) because sometimes the expression evaluated true and sometimes false.

Eliminate (C): in the second row, p was false but the expression did not evaluate to true.

Eliminate (D): in the first row, q was false but the expression did not evaluate to true.

(E) is correct. Checking the first two rows, p and q had opposite truth values and both rows evaluated to false.

Image

KEY TERMS

if

conditional statement

flow control

condition

boolean operator (==)

truth value

compound condition

&& (logical and)

|| (logical or)

! (logical not)

== (is equal to)

!= (is not equal to)

trace table

blocking

short-circuit evaluation

CHAPTER 5 REVIEW DRILL

Answers to the review questions can be found in Chapter 13.

1.Consider the following code segment:

for (int i = 200; i > 0; i /= 3)

{

if (i % 2 == 0)

System.out.print(i + “ ”);

}

What is the output as a result of executing the code segment?

(A) 200 66 22 7 2

(B) 66 22 7 2

(C) 200 66 22 2

(D) 200 66 22

(E) 7

2.Suppose p and q are declared as boolean variables and have been initialized to unknown truth values.

What does the following boolean expression evaluate to?

(p && !q) || (p && q)

(A) The expression always evaluates to the same value as p.

(B) The expression always evaluates to the same value as q.

(C) The expression always evaluates to true.

(D) The expression always evaluates to false.

(E) The expression evaluates to true only if p and q have opposite truth values.

Summary

o Values can be compared to form boolean statements using == (equals), != (not equal), < (less than), <= (less than or equal to), > (greater than), and >= (greater than or equal to).

o Boolean statements can be combined using && (and), || (or), and ! (not).

o If statements can be used to allow a command or series of commands to be executed once only if a certain boolean statement is true. Else statements can be used to execute a different command if that condition is not met.