By the end of this module, for simple programs with real
numbers, you will be able to:
Declare and use Boolean variables.
Evaluate Boolean expressions.
Declare and use Boolean arrays.
2.0 Audio:
2.0 Boolean variables
What is a Boolean variable?
An int variable takes integer values like:
12, 256, or -9.
A double variable takes on values
like 3.141, -14.0, or 2.718.
A boolean variable takes on one
of only two values: true or false.
An example:
boolean, true and false are reserved words.
Note: true and false are not in quotes.
Boolean operators:
Recall: an operator is something that "acts" on the
values of variables (like multiply takes two values
and does the familiar multiplication of those values).
Thus, a Boolean operator will "do things" with Boolean
values like
true and false.
Two binary operators: && and ||
One unary operator: !
An example:
To understand the && operator:
Let's see what c could be based on all possible
combinations of a and b values:
a
b
c = a && b
false
false
false
false
true
false
true
true
true
true
false
false
In short, the result of an AND operation
is true only when both operands are true.
Similarly, let's look at the || operator:
Let's see what c could be based on all possible
combinations of a and b values:
a
b
c = a || b
false
false
false
false
true
true
true
true
true
true
false
true
In short, the result of an OR operation
is false only when both operands are false.
The ! operator:
a
!a
true
false
false
true
In short, the NOT operator flips the value.
Note: the above table describes some of the "rules" for logic.
Let's do a few examples.
First, consider
public class BooleanExample2 {
public static void main (String[] argv)
{
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
boolean w = a && b;
System.out.println (w);
boolean x = a && c;
System.out.println (x);
boolean y = a || b;
System.out.println (y);
boolean z = b || d;
System.out.println (z);
boolean u = !a;
System.out.println (u);
}
}
2.1 Exercise:
Type up (in
BooleanExamle2.java)
and see what the above prints out.
Now let's explain:
First, look at:
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Here, there are four boolean variables, each of which
is assigned a (boolean) value.
Think of the variables as "boxes" in the usual way but
as boxes that can hold only boolean values
(true or
false).
Next, look at
boolean w = a && b;
System.out.println (w);
We know that
a
has the value
true
in it, while
b
has the value
false.
Thus, the
&&
operator is applied to the values
true
and
false.
You can picture this as:
true &&false.
What is the result?
Similar to applying the "rules of multiplication" to two numbers,
we apply the rules of AND (that is,
&&)
to
true
and
false.
The result is:
false.
Thus, the value
false
is assigned to the variable
w.
This is what's printed.
Similarly, with
boolean y = a || b;
System.out.println (y);
the result is
true
The unary operation
!
is a bit different:
boolean u = ! a;
System.out.println (u);
Here, the value in
a
is copied and "flipped" to its opposite.
Thus, because the value in
a
is
true
the result is
false
This is what gets assigned to the variable
u.
2.2 Video:
2.1 Combining Boolean operators
Just as many
int
or
double
variables can be combined in an expression like
(i*j) - a/(a+b)
so can
boolean
variables:
Consider these examples:
boolean v = (a && b) || (a || d);
System.out.println (v);
boolean s = (!v) || (! (b && c));
System.out.println (s);
We can draw an expression tree to help us evaluate
(by hand) the first expression:
The expression tree is just something we do on paper to
understand the result.
What's interesting is that "under the hood", a similar
tree is constructed by
javac
when the program is compiled.
2.3 Exercise:
In module2.pdf,
draw the expression tree for the second expression
above and evaluate it.
2.2 Boolean operators and other types of variables
Boolean operators and values arise most frequently with
working with numbers.
For example, consider this example:
int age = IOTool.readIntFromTerminal ("Enter your age: ");
if (age >= 100) {
System.out.println ("May everyone be so fortunate");
}
Let's pay attention to the condition
(age > 100).
This is really a Boolean result: it's either true or false.
Thus, we could have written:
int age = IOTool.readIntFromTerminal ("Enter your age: ");
boolean isCentenarian = (age >= 100);
if (isCentenarian) {
System.out.println ("May everyone be so fortunate");
}
Notice that the Boolean result of
(age > 100).
(which is either
true
or
false
will get assigned to the
boolean
variable
isCentenarian.
Also, we can use Boolean variables directly as
the expression for a conditional (if) statement.
It is even more common to combine multiple such comparisons
into a single expression:
int age = IOTool.readIntFromTerminal ("Enter your age: ");
if (age >= 100) {
System.out.println ("May everyone be so fortunate");
}
else if ( (age >= 90) && (age < 100) ) {
System.out.println ("Hey, that's not so bad");
}
Here, we've combined two Boolean expressions:
The expression
(age < 100)
The expression
(age >= 90)
using the
&&
(AND) operator.
Each part (often called a clause) evaluates to
either
true
or
false.
For example, suppose the
age
entered was 31.
The clause (Boolean expression)
(age >= 90)
evaluates to
false.
The clause
(age < 100)
evaluates to
true.
Then the large expression turns out to be
(false) && (true)
which evaluates to
false.
Thus, one would not enter the
else if block of code.
In the diagramming approach:
Lastly: did you notice how the parentheses were deployed
to have the overall expression make sense?
Boolean expression can get as complex as desired, for example:
int age = IOTool.readIntFromTerminal ("Enter your age: ");
int hours = IOTool.readIntFromTerminal ("Hours of exercise/day: ");
if ( ( (age >= 90) && (hours > 2) )
||
( (age < 10) && (hours > 3) ) ) {
System.out.println ("That may be too much exercise");
}
2.4 Exercise:
In module2.pdf,
draw the expression tree for the expression
above and evaluate it when age=5 and hours=3.
2.5 Exercise:
Consider this code example:
int k = 5;
int m = 3;
int n = 8;
boolean a = true;
boolean b = false;
char ch = 'q';
boolean first = (m < k) && (n > k);
boolean second = ( (k+m == n) || (k-m < 10) );
boolean third = first && (!second);
boolean fourth = (first || a) && (b);
boolean fifth = (ch >= 'a') && (ch <= 'z');
If one were to print the last five (Boolean) variables, what
would be printed out? Do the exercise without writing code
and by drawing expression trees in
in module2.pdf.
2.6 Video:
2.3 Using Boolean variables
Let's now use Boolean variables in a few examples.
Suppose we wish to solve the following problem:
We are given an array of integers and an additional integer.
Our goal is to search the array to see if the
additional integer is in the array.
We are to print "found" if it's there, else "not found" if it's not there.
Consider this program:
2.7 Exercise:
Trace through the program
in module2.pdf.
Explain why this does not accomplish the task.
Let's make another attempt:
2.8 Exercise:
Explain why this does not accomplish the task either
(in module2.pdf).
Instead, let's use a Boolean variable to flag whether
we've found the item in the array.
2.9 Exercise:
Trace through and convince yourself that this works.
Try another searchvalue that isn't actually in the array.
Will this work if found is initialized to true?
Note: one can replace if (found == true)
with if (found):
2.10 Video:
2.4 Boolean arrays
Just as we created arrays of int's or
double's, we can create boolean arrays.
For example:
Observe how similar the declaration is to an integer array:
Again, space is created using the new reserved word:
2.11 Exercise:
Suppose we replaced the second for-loop with
Without typing up the program, identify what gets
printed out.
Next, let's develop an application in steps:
counting all the prime numbers
less than or equal to some given n.
We'll exclude 2 (a prime number) for the moment, to simplify the
code a little.
Let's start by eliminating all the numbers divisible by 2 (but
starting from 3 onwards because 2 is prime by definition):
Of course, these are not the prime numbers (yet) because
they have some numbers divisible by 3, by 5 etc.
Notice the general idea:
We start by assuming all are prime.
Then, we eliminate all that are divisible by 2.
2.12 Exercise:
Why do we create an array of size n+1 above?
Why do the second and third for-loops begin with 3?
2.13 Exercise:
Modify the above code so that we eliminate both multiples
of 2 and multiples of 3.
Write your code in
PrimeExercise.java.
To identify the primes we need to eliminate all numbers
that are divisible by some other number, that is:
Remove all number divisible by 2.
Then, remove all number divisible by 3.
Then, remove all number divisible by 4.
... and so on.
When do we stop?
Thus, we will replace the second for-loop with this
nested one:
Thus, we first eliminate all numbers divisible by
k=2 (outermost loop).
Then, we eliminate all numbers divisible by k=3, etc.
2.14 Exercise:
Implement the above program
(in
MyPrimes.java)
to count the primes, and confirm
that it works.
2.15 Exercise:
In module2.pdf,
trace through the above loop when n=15 by drawing
picture of the array and its contents after each outerloop iteration.
2.16 Exercise:
You should notice some unnecessary iterations through the
outer for-loop. What is a more reasonable upper limit for
the outer loop?
2.17 Exercise:
Go back to Module 0 of Unit 0 to examine the first of the
two programs on primes.
2.5 Reading and writing
First, the term boolean:
Why such a strange word?
George Boole was among the earliest mathematicians who
realized that, just like numbers, logical values (true/false)
have their own rules of combination (that is, an algebra).
The term Boolean algebra now means the
"algebra of Boolean variables", where the operators
are different from the numeric operators we're used to (like
subtraction, division).
As we've seen, some Boolean operators are AND, OR, NOT.
In Java, these three are represented by
&&, ||, !.
In case you're wondering ... these three operators suffice
for just about everything that's needed from Boolean variables.
We use the reserved
word boolean:
for Boolean variables in Java.
Note: many earlier languages did not have such a
specific type set aside for Boolean values and instead
"faked it" with the numbers 0 and 1.
One of the most common uses of Boolean variables is as
a flag variable:
Consider this example:
boolean containsNegative = false;
for (int i=0; i<data.length; i++) {
if (data[i] < 0) {
containsNegative = true;
}
}
Here, we initialize a flag (the Boolean variable
containsNegative)
to
false.
boolean containsNegative = false;
Then, when going through the array, we look to see
if we need to "flag" that we've found a negative value.
if (data[i] < 0) {
containsNegative = true;
}
So, at the end, if it is true that there's a negative
value, we can do something:
// Later in the program ...
if (containsNegative) {
// Do something ...
}
2.18 Exercise:
In MultiplesOf3.java,
add code to "flag" whether or not an array of numbers
contains a multiple of 3. Start with this template in
main:
public static void main (String[] argv)
{
int[] someNumbers = {1, 4, 9, 16, 25};
// Write your code here ...
}
Neatness in writing large Boolean expressions:
Consider this example:
if (((age > 0) && (age < 12) && (withAdult)) || (age > 12)) {
System.out.println ("OK to watch this movie");
}
It is hard to read the intention here.
Using spaces and multiple lines helps make the intention
clear:
if ( ( (age > 0) && (age < 12) && (withAdult) )
||
(age > 12) ) {
System.out.println ("OK to watch this movie");
}
Notice the subtle lining up of equivalent Boolean blocks:
if ( ( (age > 0) && (age < 12) && (withAdult) )||(age > 12) ) {
System.out.println ("OK to watch this movie");
}
That is, the entire expression
( (age > 0) && (age < 12) && (withAdult) )
is parallel to
(age > 12)
because the two expressions are on either side of the OR operator
||.
It is easy to make a mistake if you don't use meaningful style
when writing.
Whitespace in expressions:
Above, we wrote:
( (age > 0) && (age < 12) && (withAdult) )
Some people will leave out the whitespace around operators:
( (age>0) && (age<12) && (withAdult) )
Generally, in the early coursework, we'd prefer exploiting
whitespace to add clarity.
When you are a much more experienced programmer, you can
opt for less whitespace.
The one big exception is the use of whitespace in
the three expresions that comprise a for-loop. We typically
do NOT surround the operators with whitespace.
Thus, we write
for (int i=0; i<10; i++) {
// Whatever ...
}
and NOT
for (int i = 0; i < 10; i ++) {
// Whatever ...
}
Why? It's just how the convention around loops has come to be.
Perhaps because the added whitespace makes it hard to see the
three different pieces of the loop's parameters.
2.6 When things go wrong
2.19 Exercise:
In PG13.java
type up
int age = 12;
boolean withAdult = true;
if ( ( (age > 0) && (age < 12) && (withAdult) )
||
(age > 12) ) {
System.out.println ("OK to watch this movie");
}
and identify the logical error.
2.20 Exercise:
Without writing up the code, identify the error below
if (age = 12) {
System.out.println ("Fine, you can watch");
}
2.21 Exercise:
In RoundOffError.java,
write up
double x = Math.sqrt (2);
double y = x * x;
if (y == 2) {
System.out.println ("They're equal");
}
How would you fix the problem?
2.22 Exercise:
Without writing it up, find the logical error here:
boolean allPositive = false;
int[] someNumbers = {1, 2, 3};
for (int i=0; i<someNumbers.length; i++) {
if (someNumbers[i] < 0) {
allPositive = false;
}
}
if (allPositive) {
System.out.println ("They're all positive");
}