Objectives
- Use while statements
- Use fencepost loops
- Use the boolean type
- Use while statements to handle user errors
- Introduce assertions
Assignments
- Read Chapter 5
- Quiz 8 Available end of Week 11
- Project 2 Due beginning of Week 11
- Lab 6 Due beginning of Week 12
- Quiz 9 Available end of Week 12
- Lab 7 Due beginning of Week 13
- Introduce Project 3
Contents
While Loops
Definite Loops
The for loops that we have been writing are
definite loops;
before the loop, we know how many times the loop will be
executed. Some examples are:
- Print "hello" 10 times.
for (int i = 1; i <= 10; i++) {
System.out.println("hello");
}
- Sum the odd numbers between 10 and 99. How many times will
this loop be executed?
int sum = 0;
for (int j = 10; j <= 99; j++) {
if (j % 2 == 1) {
sum += j;
}
}
- Count the number of blanks in a string. How many times will
this loop be executed?
String s = "To be or not to be";
int count = 0;
for (int k = 0; k < s.length(); k++) {
if (' ' == s.charAt(k)) {
count++;
}
}
Indefinite Loops
An
indefinite loop is a loop in which it is
unclear how many times it will be executed. Here is an example
of an indefinite loop implemented by a
while loop.
double r = Math.random();
while (r < 0.5) {
r = Math.random();
}
Recall that
Math.random() generates a random
double
between 0 and 1. The code initializes
r to a random
number. If
r < 0.5, then another random
number is assigned to
r, and the flow of control goes back to
the test. This code will loop as long
as
r < 0.5. Because of the randomness, we
don't know how many times the loop will be executed.
Activity: Implement a program including the above while
loop. Print out every value that is assigned
to r. Add a counter to count how many times the body of
the loop is executed. Run the program several times to see how
its behavior varies.
Behavior of While Loops
A while loop repeatedly executes its body as long as its test is
true. The syntax of the while statement is:
while (test) {
statement(s);
}
A while loop is executed in the following manner:
- If the test is false, go to step 4.
- Execute the body of the loop, that is, the statements inside
the curly braces.
- Go to step 1.
- Execute the statement(s) after the loop.
Here is another example of a while loop:
int num = 1;
while (num < 200) {
System.out.print(num + " ");
num *= 2;
}
System.out.println(num);
Before the loop, the variable
num is initialized to 1.
The body of the loop will be repeated as long
as
num < 200. Inside the loop, the first
statement prints
num, and the second statement
multiplies
num times 2. The code keeps
doubling
num as long
as
num < 200. The output is:
Today's News: November 3
This is the start of Week 11
Project 2 is due today.
Activity: Divide by 2
Write and test a while loop to keep dividing
an
int by 2 until 0 is reached. Make
sure your loop works with different initial integers, including
negative ones. This is what should print if you start with 100.
Activity: Eliminate right digit
Write and test a while loop to print out the following
sequence in which the rightmost digit is eliminated each time. Make
sure your loop works with different initial integers, including
negative ones.
1048576 104857 10485 1048 104 10 1 0
Activity: Hailstone
Write and test a while loop to print out the following
"hailstone" sequence.
17 52 26 13 40 20 10 5 16 8 4 2 1
A hailstone sequence is generated as follows. Let
n be
the current number. If
n is odd, the next number
is
3 * n + 1. If
n is
even, the next number is
n / 2. The sequence
ends when the current number is
1. Try starting with
different positive integers.
Activity: Fibonacci
Write and test a while loop to print out the
Fibonacci numbers that are less than 100.
0 1 1 2 3 5 8 13 21 34 55 89
The Fibonacci sequence starts with 0 and 1. After that, the next
number is the sum of the two previous numbers.
Book: Read about do-while loops and rewrite the first while
loop above as a do-while loop.
While Loops 1
Random Numbers
The Random class
A Random object generates
pseudorandom numbers.
Pseudorandom means that the numbers are generated in a
well-defined way, but the sequence of numbers looks random (satisfies many
mathematical properties of random numbers). The Random
class is found in the java.util package.
The Random class includes the following constructor and methods:
Constructor | Description |
new Random( ) | a new Random object |
Method name | Description |
nextInt(max) | returns a random int between 0
and max – 1 |
nextDouble( ) | returns a
random double between 0.0 and 1.0 |
nextBoolean( ) | returns true
or false randomly |
|
Here is an example that generates a random integer between 0 and
9.
Random randomObject = new Random();
int randomNumber = randomObject.nextInt(10);
Here are more examples assuming
randomObject is a Random
object.
- To generate a random integer between 1 and some value, you need
to add 1. This generates a random number from 1 to 10.
int rating = 1 + randomObject.nextInt(10);
- To generate a random integer in some range, you need to figure out
how many integers are in the range, and add the first value.
Suppose the range is from 5 to 15. There are 11 values in this
range, and 5 is the first number.
int inRange = 5 + randomObject.nextInt(11);
- To generate a random double in some range, you need to
figure out the difference between the maximum and the minimum, and you
need to add the minimum. Suppose the range is from 1.3 to
4.2 The difference is 2.9, and 1.3 is the minimum.
double d = 1.3 + 2.9 * randomObject.nextDouble( );
Activity: Simple Random Numbers
Given the following declaration,
Random rand = new Random( );
how would you get:
- a random integer between 1 and 100 inclusive?
- a random integer between 50 and 100 inclusive?
- a random integer between 4 and 17 inclusive?
- a random GPA value between 1.5 and 4.0?
Activity: Random until 10
Write a while loop that generates random integers
between 1 and 10 until a 10 is generated.
Simple Random Numbers
Today's News: November 5
Quiz 8 available, due Saturday
Simulations
Pseudorandom numbers are often used in simulations because they can be
used to mimic random variations in the real world. Loops are
used in simulations for many reasons: to loop over different points in time,
different regions in space, different components of a device,
different objects in an environment, different initial conditions.
For example, consider a program that simulates rolling of two
6-sided dice, continuing until a 7 is rolled.
Roll die 1.
Roll die 2.
If the sum if 7, stop.
else roll both dice again.
To turn this into a loop, we need to figure out the test that
indicates that we want to continue the loop. A sum of 7 is when
we want to stop, so a sum not equal to 7 is when we want to continue.
While the sum of the dice is not equal to 7:
Roll die 1.
Roll die 2.
What is the sum of the dice before the loop? One option is to
add two dice rolls before the loop.
Roll die 1.
Roll die 2.
While the sum of the dice is not equal to 7:
Roll die 1.
Roll die 2.
Another option is to
prime the loop, to initialize the
variable(s) being tested so that the test is true. In this case,
we can initialize the sum to some value other than 7. Our
pseudocode also includes more detail on computing the sum.
Initialize sum to 0.
While the sum of the dice is not equal to 7:
Roll die 1 and assign its value to roll1.
Roll die 2 and assign its value to roll2.
Assign roll1 plus roll2 to sum.
To simulate rolling a die, we need to generate a random integer
between 1 and 6. Our implementation will include a Random object
and call the nextInt method.
Construct a Random object.
Initialize sum to 0.
While the sum of the dice is not equal to 7:
Call the nextInt method of the Random object with
parameter 6.
Assign this value plus one to roll1.
Call the nextInt method of the Random object with
parameter 6.
Assign this value plus one to roll2.
Assign roll1 plus roll2 to sum.
Now we have enough detail to write the program.
import java.util.*;
public class RollDice {
public static void main(String[] args) {
Random rand = new Random();
int sum = 0;
while (sum != 7) {
int roll1 = 1 + rand.nextInt(6);
int roll2 = 1 + rand.nextInt(6);
System.out.println("The dice are " + roll1 + " and " + roll2);
sum = roll1 + roll2;
}
}
}
Activity: Roll 2 dice
Write a method called rollTwoDice which takes a Random as a parameter,
simulates the rolling to two dice, and returns the sum from that roll.
Use this method to rewrite then above program.
Activity: Rock Paper Scissors
Write a program to play rock-paper-scissors, you
against the computer.
Use the integers 0, 1, 2 to represent rock, paper, and scissors.
The program should continue until one of the players wins a round.
Activity: Multiplication Tutor
Write a program to be a multiplication tutor.
Ask the user to solve problems with random numbers from 1 to 20.
The program should stop after an incorrect answer.
Dice Simulation
Fencepost Loops
Consider writing a program to print the integers from 1 up to a
constant separated by commas. Here is an example from 1 to 5.
Note that we print 5 numbers, but only 4 commas. This is solved
using a
fencepost loop. The loop will print the 4 commas
and 4 of the numbers. The other number is printed
outside
of the loop. One solution is print 1 before the loop.
Assume that the maximum number to be printed is assigned to a constant
named
MAX_NUMBER.
System.out.print(1);
for (int i = 2; i <= MAX_NUMBER; i++) {
System.out.print(", ");
System.out.print(i);
}
Another solution is to print the constant after the loop. Note
what limits are chosen for both for loops.
for (int i = 1; i < MAX_NUMBER; i++) {
System.out.print(i);
System.out.print(", ");
}
System.out.print(MAX_NUMBER);
Yet another solution is to put an if statement inside the loop to
control when the comma is printed. This is the only solution
that does not print anything if
MAX_NUMBER is zero.
for (int i = 1; i <= MAX_NUMBER; i++) {
System.out.print(i);
if (i < MAX_NUMBER) {
System.out.print(", ");
}
}
Activity: Numbers in brackets
Write a program to print the integers from 1 up to a
user entered number, where the numbers are separated by spaces
surrounded by square brackets. Here is an example from 1 to 5.
Numbers in brackets
Today's News: November 7
Quiz 8 available, due Saturday
Lab 6 due on Tuesday
Sentinel Loops
Suppose we want the user to be able to sum up any number of
values. In our previous solution, the user had to first enter
the number of values to be summed. If we want to avoid asking
for this information, we need to have some other way to detect the end
of the input. One method is to use a
sentinal value,
which is a specific value that signals the end of input.
Suppose that we use
-999 as the sentinel value.
Before we write a loop, let's look at one possible sequence of events.
Initialize sum to 0.
Prompt the user and read a value.
The input value is not equal to -999.
Add the value to sum.
Prompt the user and read a value.
The input value is not equal to -999.
Add the value to sum.
Prompt the user and read a value.
The input value is equal to -999.
Print sum and finish.
Note that this sequence has the properties of a fencepost loop.
There are 3 values that are read, but only 2 of the values are added
to the sum. Also, note that we want to continue when the input
value is not equal to the sentinal value, and note the order of
operations between two tests. From these observations, the
pseudocode can be refined with a loop.
Initialize sum to 0.
Prompt the user and read a value.
While the input value is not equal to -999:
Add the value to sum.
Prompt the user and read a value.
Print sum and finish.
We now have enough information to convert this into a while loop in
Java.
Scanner console = new Scanner(System.in);
int sum = 0;
System.out.print("Enter first integer (-999 to quit): ");
int value = console.nextInt( );
while (value != -999) {
sum += value;
System.out.print("Enter next integer (-999 to quit): ");
value = console.nextInt( );
}
System.out.print("The sum is " + sum);
Activity: Sentinal Loops 1
Write a program to test the above code. Allow
the user to enter a sentinal value. Also, print the average; be
sure that it works if the sentinel value is the first value that is
entered.
Activity: Sentinal Loops 2
Write and test a program that repeatedly prompts the
user for words until the user types "goodbye", then outputs the
longest word that was typed. In this case, "goodbye" is the
sentinel value.
Sentinal Loops
The boolean Type
boolean is a Java type whose values are
true and
false. A test in an if, for, or while is a boolean
expression (a test evaluates to either
true or
false). You can create and use
boolean variables,
pass
boolean parameters, and return
boolean values
from methods.
Here is an example of using
boolean variables.
Note how
boolean expressions are assigned to the
boolean variables. Also note that the test of each
if statement is just a
boolean variable; all Java cares about
is whether the test evaluates to
true or
false.
Scanner console = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = console.nextInt( );
boolean tobaccoLegal = (age >= 18);
if (tobaccoLegal) {
System.out.println("You can buy tobacco.");
} else {
System.out.println("You can't buy tobacco.");
}
boolean alcoholLegal = (age >= 21);
if (alcoholLegal) {
System.out.println("You can buy alcohol.");
} else {
System.out.println("You can't buy alcohol.");
}
Activity: Tobacco and Alcohol
Rewrite the above code so it uses the
boolean
variables to print one of the following:
- You can buy tobacco and alcohol.
- You can buy tobacco, but not alcohol.
- You can't buy tobacco or alcohol.
Activity: MPAA Movie Ratings
Based on the age and the
MPAA movie ratings, use
boolean variables to
selectively print out what movies the person is allowed to see.
Activity: UTSA Bulletin
Using the information in
the
UTSA
Information Bulletin, write and test a program that inputs the
number of credit hours and classifies an undergraduate student as a
senior, junior, sophomore, or freshman. The program should have
boolean variables
named
senior,
junior,
sophomore, and
freshman and should assign appropriate
boolean expressions
to each of them. You should make sure that only one of these
variables is
true (except that all four
boolean
variables should be
false if the number of credit hours is a
negative number).
Logical Operators
boolean variables and
boolean expressions can be
combined using logical operators.
Operator | Meaning |
Example True | Example False |
&& | AND |
1 < 2 && 3 < 4 | 1 < 2 && 3 > 4 |
|| | OR |
1 == 2 || 1 != 2 | 1 > 2 || 3 > 4 |
! | NOT |
! (1 > 2) | ! (1 < 2) |
A
truth table shows how logical operators are evaluated. In
the truth table below,
p is a
boolean variable. For each value of
p, the
corresponding value of
! p is shown.
p | ! p |
true | false |
false | true |
The truth table for
&& shows that this operator
evaluates to true only if both operands (
p and
q)
are true.
p | q |
p && q |
true | true | true |
true | false | false |
false | true | false |
false | false | false |
The truth table for
|| shows that this operator
evaluates to true if either operand (or both operands)
are true.
p | q |
p || q |
true | true | true |
true | false | true |
false | true | true |
false | false | false |
Activity: Relational and Logical Operators
Given
int x = 42;
int y = 17;
int z = 25;
What is the result of each of the following expressions?
Note that the arithmetic operators have a higher precedence than
the relational operators, which, in turn, have higher precedence than
&&, which has a higher precedence than
||.
- y < x && y <= z
- x % 2 == y % 2 || x % 2 == z % 2
- x <= y + z && x >= y + z
- ! (x < y && x < z)
- (x + y) % 2 == 0 || ! ((z - y) % 2 == 0)
- x < y || y == z && z == x
- x == y && y == z || z < x
Try to come up with
different values for
x,
y, and
z that will
have opposite results.
Activity: Relational and Logical Operators
Methods That Return boolean
Methods can return
boolean values.
A call to such a method can be a loop or if test.
For example, the
equals and
startsWith methods
of the String class return
booleans.
Scanner console = new Scanner(System.in);
String answer = "yes"; // priming the loop
while (answer.equals("yes")) { // don't use == with Strings
System.out.print("Enter yes to continue: ");
answer = console.next( );
}
System.out.print("Are you sure you want to stop? ");
answer = console.next( );
while (answer.startWith("n")) {
System.out.print("Are you sure yet? ");
answer = console.next( );
}
To write a
boolean method, we specify the return type as
boolean and, in the body of the method, we write return
statements to return
true,
false, a
boolean
variable, or a
boolean expression.
Suppose we want to write a method that returns
true if both
parameters are odd. To test whether
x is odd, we can
write the test
x % 2 == 1, that is, whether the
remainder is 1 after dividing by 2. There are a number of ways
to code the method.
public static boolean bothOdd1(int a, int b) {
if (a % 2 == 1) {
if (b % 2 == 1) {
return true;
}
}
return false;
}
public static boolean bothOdd2(int a, int b) {
if (a % 2 != 1) {
return false;
}
if (b % 2 != 1) {
return false;
}
return true;
}
public static boolean bothOdd3(int a, int b) {
if (a % 2 == 1 &&b % 2 == 1) {
return true;
} else {
return false;
}
}
public static boolean bothOdd4(int a, int b) {
return (a % 2 == 1 && b % 2 == 1);
}
The last method would be considered the most elegant. It simply
returns the value of the
boolean expression.
Today's News: November 10
Lab 6 due on Tuesday
Activity: Boolean Methods
Write
boolean methods for some of the
following tasks:
- Return true if one parameter is odd and the other parameter is
even.
- Return true if at least two of the three parameters are odd.
- Return true if the char parameter is a vowel.
- Return true if the String parameter contains a vowel.
- Return true if all the characters in the String parameter
are vowels.
- Return true if none of the characters in the String parameter
is a vowel.
- Return true if the integer contains an odd digit.
- Return true if all the digits in the integer are odd.
Activity: Boolean Methods
Advanced boolean Topics
Short-Circuited Evaluation
Suppose we want to write a test whether the third character of a
String named
answer is an
's'. The straightforward
way to code this test:
(answer.charAt(2) == 's')
has a serious bug. If
answer has fewer than 3
characters, this will cause an exception. In Java, we can use
short-circuited evaluation to test the length of
answer
first, and then use
&& with the
above
boolean expression.
(answer.length() >= 3 && answer.charAt(2) == 's')
If the first operand
answer.length() >= 3 is false, then Java
knows the result of the
&& will be false, so Java
does not evaluate the second operand, and an
exception will be avoided. Short-circuited evaluation also applies
to
||; if the first operand of an
|| is true, then
Java knows the result of the
|| will be true, and so
Java does not evaluate the second operand.
Activity: Short Circuit Evaluation
Rewrite the following
boolean expressions
to avoid a potential exception. Assume
str is a String object.
- Character.isLetter(str.charAt(3))
- str.substring(0,5).equals("Hello")
- str.substring(7,12).equals("world")
Activity: Short Circuit Evaluation
De Morgan's Laws
Sometimes you want to write the negation of a
boolean
expression. Consider the following two
boolean expressions.
(score >=0 && score <= 100)
(answer == 'y' || answer == 'Y')
The first expression might test whether
score is a valid
score. The second expression might test whether
answer
is
'y', either lowercase or uppercase. The simplest
way to negate these expression is with
!.
(! (score >=0 && score <= 100))
(! (answer == 'y' || answer == 'Y'))
However, using
! in this way can be difficult to understand
in larger expressions. Another approach is to transform these
expressions using
De Morgan's Laws, which are rules used to
negate or reverse boolean expressions. They are useful when you
want the opposite of a known boolean test.
Original Expression |
Negated Expression |
Equivalent Alternative |
p && q |
! (p && q) |
(! p) || (! q) |
p || q |
! (p || q) |
(! p) && (! q) |
For example, De Morgan's Laws justify the following statements.
(! (score >= 0 && score <= 100))
is equivalent to
(! (score >= 0) || ! (score <= 100))
(! (answer == 'y' || answer == 'Y'))
is equivalent to
(! (answer == 'y') && ! (answer == 'Y'))
To finish with a simpler expression, we need to remember that
< is the opposite of
>=, that
> is the opposite of
<=, and that
!= is the opposite of
==. With this mind, we
can justify the following:
(! (score >= 0 && score <= 100))
is equivalent to
(! (score >= 0) || ! (score <= 100))
which in turn is equivalent to
(score < 0 || score > 100)
(! (answer == 'y' || answer == 'Y'))
is equivalent to
(! (answer == 'y') && ! (answer == 'Y'))
which in turn is equivalent to
(answer != 'y' && answer != 'Y')
Activity: De Morgan's Laws
Convert the following
boolean expressions
using De Morgan's Laws.
- (! (gpa >= 0.0 && gpa <= 4.0))
- (! (diff >= -epsilon && diff <= epsilon))
- (! (answer.length() >= 3 && answer.charAt(2) == 's'))
- (! (gender == 'F' || gender == 'M'))
- (! (grade == 'A' || grade == 'B' || grade =='C'))
- (! (Character.isLetter(ch) || Character.isDigit(ch)))
Activity: De Morgan's Laws
User Errors
When you are writing interactive programs, it would be nice to assume
that the user will always provide good input. Unfortunately,
users are not that well-behaved. By now, you have probably
entered bad data a few times, perhaps bad enough to cause
exceptions. Because of user errors, it is best to write programs
that are
robust, that continue to execute properly even with
bad data.
While loops are often used with Scanner input to continue in a loop as
long as the user enters bad data. Consider
writing a program that repeatedly prompts until the user types a
non-negative number, and then computes and prints its square
root. Here is one possible sequence of events.
Prompt the user and read a value.
The input value is negative.
Prompt the user and read a value.
The input value is negative.
Prompt the user and read a value.
The input value is negative.
Prompt the user and read a value.
The input value is not negative.
Compute and print square root.
As long the input value is negative, we want to continue
prompting the user and reading a value. Our next step
is to modify the pseudocode into a while loop.
Prompt the user and read a value.
While the input value is negative:
Prompt the user and read a value.
Compute and print square root.
Finally, this pseudocode can be coded in Java.
Scanner console = new Scanner(System.in);
System.out.print("Enter a nonnegative number: ");
double num = console.nextDouble( );
while (num < 0) {
System.out.print("Invalid number, try again: ");
num = console.nextDouble( );
}
double root = Math.sqrt(num);
System.out.print("The square root of " + num + " is " + root);
Activity: User Errors 1
Write and test a loop that ensures that a user
enters an int between 1 and 5.
Activity: User Errors 2
Write and test a loop that ensures that a user
enters yes or no.
Activity: User Errors 3
Write and test a loop that ensures that a user
enters a single character.
Today's News: November 12
Quiz 9 available, due Saturday
Scanner Lookahead
However, if the user does not enter a number, this code will still cause
an exception. To avoid this problem, we can use methods of the
Scanner class that look ahead to see what kind of input has been
entered.
Method name | Description |
hasNext( ) | returns true if the next
token can be read as a String |
hasNextInt( ) | returns true if the next
token can be read as an int |
hasNextDouble( ) | returns true if the next
token can be read as a double |
For user input,
hasNext will always return
true, but
hasNextInt and
hasNextDouble will only
return
true if the next token is a number of that type. Also, if
you want the user to enter an
int and
hasNextInt
returns
false, then you need to call the
next method
to read the non-
int token before you can try to read a
different token. Here is a possible sequence of events.
Prompt the user.
The input value is not an int.
Read and discard a String.
Prompt the user.
The input value is not an int.
Read and discard a String.
Prompt the user.
The input value is an int.
Read an int.
Here is pseudocode with a loop.
Prompt the user.
While the input value is not an int:
Read and discard a String.
Prompt the user.
Read an int.
Note that we want to continue the loop
as long as
hasNextInt returns
false. This
is a good spot to use the
! operator to reverse the
return value of
hasNextInt. Here is the Java code.
Scanner console = new Scanner(System.in);
System.out.print("Enter an int: ");
while (! console.hasNextInt( )) {
String trash = console.next( );
System.out.println("You did not enter an int: " + trash);
System.out.print("Enter an int: ");
}
int keeper = console.nextInt( );
System.out.println("You entered an int: " + keeper);
Activity: Scanner Lookahead
Write and test a loop that ensures that a user
enters a double.
Activity: User Errors and Scanner Lookahead
boolean Flags
Consider again writing a program that repeatedly prompts until the
user types a non-negative number, and then computes and prints its
square root. This time we want to avoid an exception if the user
does not enter a number. Handling a negative number
involves a different sequence of actions than handling an input that
is not a number.
boolean flags
- This is what happens if the input is negative.
Prompt the user.
The input value is a double.
Read the input value.
The input value is negative.
Prompt the user.
....
-
This is what happens if the input is not a number.
Prompt the user.
The input value is not a double.
Read and discard the input.
Prompt the user.
....
Note that the first sequence involves two tests with an action between
them. The first test is whether the next token is
a
double. The action is to read the token. The
next test is whether the input is negative. Also, we need to
make sure that the program does something different if the next token
is not a
double. How do we write a loop that involves
such a complicated test?
One method is to use a
flag, which is a
boolean
variable that is used to manage the flow of control. For a
loop, the basic pseudocode pattern for a flag is:
Initialize flag to true.
While the flag is true:
Do stuff.
Make sure the flag is false at this point if you want the loop to stop.
Let's do a first pass of what this might look like for the
square root problem. Clearly, the first test will be whether
the next token is a double or not (using the
hasNextDouble
method). Based on the result of this test, the program should
read a
double (using the
nextDouble method) or a
String (using the
next method).
Initialize flag to true.
Prompt the user.
While the flag is true:
If the next token is a double:
Read a double.
Else:
Read a String.
Compute and print square root.
The program should set the flag to
false if the next token is
a
double and it is not negative. If the next token is a
String, the flag should remain
true.
Initialize flag to true.
Prompt the user.
While the flag is true:
If the next token is a double:
Read a double.
If the input is not negative:
Set the flag to false.
Else:
Read a String.
Compute and print square root.
This can be converted to the following Java code,
where
continueLoop is the name of the flag.
Scanner console = new Scanner(System.in);
boolean continueLoop = true;
double num = -1; // need to declare num outside the loop
System.out.print("Enter a nonnegative number: ");
while (continueLoop) {
if (console.hasNextDouble( )) {
num = console.nextDouble( );
if (num >= 0) {
continueLoop = false;
}
} else {
String trash = console.next( );
}
}
double root = Math.sqrt(num);
System.out.print("The square root of " + num + " is " + root);
Activity: Boolean Flags
The above code does not print a prompt again if the
input is bad. Modify and test the code so it prompts the user
appropriately. Also, print out any bad input from the user with
an appropriate message.
Activity: Grade Point Average
Write a program that inputs a grade point average
from the user. The program should ensure that the user
enters a double between 0.0 and 4.0.
Activity: Input One of Two Values
Write a program that ensures that the user
enters an int equal to -999 or a double
equal to 3.14.
Assertions and Program Logic
An
assertion
is statement that is either true or false. Some examples are:
- Java was created in 1995.
- The sky is purple.
- 23 is a prime number.
- 10 is greater than 20.
- x divided by 2 equals 7. (depends on the value of x)
An assertion might be false ("The sky is purple" above), but
it is still an assertion because it is a true/false statement.
Suppose you have the following code:
if (x > 3) {
// Point A
x--;
} else {
// Point B
x++;
}
// Point C
What do you know about
x's value at the three points?
Is
x > 3? Always? Sometimes?
Never?
We can make assertions at various points in the code and ask whether
they are true. Valid answers are
always,
never,
or
sometimes. The answer should be "always" if the
assertion is true no matter what, e.g., no matter what the user
inputs, no matter what the parameters are (if inside a method).
The answer should be "never" if the assertion is false no matter what.
System.out.print("Type a nonnegative number: ");
double number = console.nextDouble();
// Point A: is number < 0.0 here? (SOMETIMES)
while (number < 0.0) {
// Point B: is number < 0.0 here? (ALWAYS)
System.out.print("Negative; try again: ");
number = console.nextDouble();
// Point C: is number < 0.0 here? (SOMETIMES)
}
// Point D: is number < 0.0 here? (NEVER)
Today's News: November 14
Quiz 9 is due on Saturday.
Lab 7 is due on Tuesday.
Reasoning about Assertions
Right after a variable is initialized, its value is known.
int x = 3;
// is x > 0? ALWAYS
In general you know nothing about values of parameters.
public static void mystery(int a, int b) {
// is a == 10? SOMETIMES
...
}
But inside an if, while, etc., you may know something.
public static void mystery(int a, int b) {
if (a < 0) {
// is a == 10? NEVER
...
}
...
}
At the start of a loop's body, the loop's test must be true.
while (y < 10) {
// is y < 10? ALWAYS
...
}
Inside a loop's body, the loop's test may become false.
while (y < 10) {
y++;
// is y < 10? SOMETIMES
...
}
After a loop, the loop's test must be false.
while (y < 10) {
...
}
// is y < 10? NEVER
The above statement makes an assuption about the contents of the body of the loop.
What assumption is it?
Sometimes
There are several things that cause a variable's value to be unknown.
- reading from a Scanner object
- reading a number from a Random object
- a parameter's initial value to a method
If you can reach a part of the program both with one example with
the answer being "yes" and another example with the answer being "no"
(with no changes to the program),
then the correct answer is "sometimes".
Activity: Assertions 1For the following method:
public static void mystery(int x, int y) {
int z = 0;
// Point A
while (x >= y) {
// Point B
x = x - y;
// Point C
z++;
// Point D
}
// Point E
System.out.println(z);
}
which of the following assertions are true at which
point(s) in the code?
Choose ALWAYS, NEVER, or SOMETIMES.
| Point A |
Point B | Point C |
Point D | Point E |
x < y |
| | | | |
x == y |
| | | | |
z == 0 |
| | | | |
Activity: Assertions 1
Activity: Insertions 2:For the following method:
public static int mystery(Scanner console) {
int prev = 0;
int count = 0;
int next = console.nextInt();
// Point A
while (next != 0) {
// Point B
if (next == prev) {
// Point C
count++;
}
prev = next;
next = console.nextInt();
// Point D
}
// Point E
return count;
}
which of the following assertions are true at which
point(s) in the code?
Choose ALWAYS, NEVER, or SOMETIMES.
| Point A |
Point B | Point C |
Point D | Point E |
prev == 0 |
| | | | |
next == 0 |
| | | | |
next == prev |
| | | | |
Activity: Assertions 2
Activity: Assertions 3
For the following method:
// This method assumes y >= 0, and returns x^y.
public static int pow(int x, int y) {
int prod = 1;
// Point A
while (y > 0) {
// Point B
if (y % 2 == 0) {
// Point C
x = x * x;
y = y / 2;
// Point D
} else {
// Point E
prod = prod * x;
y--;
// Point F
}
}
// Point G
return prod;
}
which of the following assertions are true at which
point(s) in the code?
Choose ALWAYS, NEVER, or SOMETIMES.
| Point A |
Point B | Point C |
Point D | Point E |
Point F | Point G |
y > 0 |
| | | | |
| |
y % 2 == 0 |
| | | | |
| |
Activity: Assertions 3
Activity: Assertions 1-3