This lab introduces two Java constructs, while loops and arrays, and applies them to solve several problems.
The previous lab introduced the for loop as mechanism to iterate through a series of data or events.
for-loops are particularly common when working through a sequence of numbers or indices. For example, the following code segment computes and prints factorials from 1! to n! factorial, for a given n:
for (i = 1, factorial = 1; i <= n; factorial = factorial * i, i = i + 1) out.println (factorial);
Java also contains two other types of loops that may simplify code when a simple test is needed at the start of the end of a loop. These loop forms have the following syntax:
while (condition) do statement; statement; while (condition);
In the first case, the condition is evaluated, and the statement is executed if that condition is true. The loop continues until the condition becomes false.
In the second case, a statement is executed first, and then the condition is evaluated. If the condition is true, the statement is evaluated again. The loop continues until the condition becomes false.
Overall, the loop continues until the condition becomes false. In the first version, that condition is checked at the start, and the statement will not be executed at all if the condition is false initially. In the second version, the statements are always evaluated once, before the condition is checked. In both versions, you should use braces { } if you want to include multiple statements within the loop.
Example: The following code shows the above factorial computation, translated to these two forms:
i = 1; factorial = 1; while (i <= n) { factorial = i*factorial; i = i + 1; } i = 1; factorial = 1; do { factorial = i*factorial; i = i + 1;} while (i <= n);
Place the above three loops into a Java program, adding a read statement to determine the value of n, and adding print statements to determine the results after each code segment. Compile and run the program for several values of n. Check that the code runs correctly for positive values of n. What happens if 0 or a negative number is entered? Explain briefly.
Arrays in Java correspond to vectors in Scheme. That is, arrays provide a mechanism to store values, based on an index. As an example, program arrayExample.java reads 10 numbers, prints them out in reverse order, and finds their maximum and minimum.
As this example shows, work with an array involves two basic parts, declaration and use.
Array Declaration proceeds by declaring a variable. In the example, the relevant code is:
final int Number = 10; int[] values = new int [Number];
The first declaration indicates that variable Number will be an integer initialized to 10. The extra word final at the start of that line indicates that the value of Number cannot be changed by the program. That is, Number will have the constant value 10.
The first part of this line declares variable values as an array of integers. Specifically, int indicates the numbers in the array will be integers, and the brackets [] indicate there will be an array. The next part of the declaration initializes the variable values to be a new array of ints, and [Number] indicates the number of items in the array.
Array Use: After an array is declared, elements within the array are accessed by providing an index (placed in brackets {}). Thus, values[i] accesses the ith element of the array.
What, if anything, happens if final is omitted in the declaration of Number?
With final still omitted, what happens if Number is changed to the value 15 later in the program? Does the program still compile? Does it run correctly?
Retain the line changing Number to 15, but re-insert final when Number is declared and initialized to 10. Again, does the program compile? Does it run correctly?
Suppose int variables i and j were both declared in the program. Suppose also the first loop using index i were retained, but the second loop were changed, so all variables i in the second loop only were changed to j. Does the program still work? Explain your answer.
In ancient Greece, Eratosthenes gave the following algorithm for determining all prime numbers up to a specified number M:
A. | Keep 2, but cross out all multiples of 2 (i.e., cross out 4, 6, 8, ...). |
B. | Keep 3, but cross out all multiples of 3 (i.e., cross out 6, 9, ...). (Note: While 6 is crossed out twice, it only matters that it has been crossed out. We attach no significance to the number of times the 6 is crossed out.) |
C. | Since 4 is already crossed out, go on to the next number that is not crossed out (i.e., 5). Keep 5, but cross out all multiples of 5 (i.e., 5, 10, 15, ...). |
General Step | Suppose you have just processed the number P. Go on to the next number that is not crossed out -- Q. Keep Q, but cross out all multiples of Q. |
In translating this outline to a program, we will need to consider how to decide how to keep track of numbers and crossings out. One approach is to have an array crossedOut where crossedOut[i] is true if the value i has been crossed out previously and false if i has not been crossed out.
Program primeSieve.java now follows the above outline closely. In the program, M is read from the keyboard, and the primes are printed at the end.
Copy primeSieve.java to your account, compile, and run it.
Why do you think array crossedOut is a boolean array in this program?
Array indices in Java always start at 0, and the array initialization new boolean [N] creates an array with N elements -- numbered 0 through N-1. In primeSieve.java, what happens if crossedOut is declared as size M rather than M+1? Explain your answer briefly.
Some extra code is included at the end of primeSieve.java, so the primes will be printed out in reasonably nice columns. Explain how this formatting is implemented.
Now that you have seen several examples of loops and arrays, it is your turn. Here are some problems involving simple simulations.
Rolling a Die: Using the random method in the Math class, we can simulate the rolling of a die as follows.
Since Math.random() returns a random number between 0.0 and 1.0, the expression 6.0*Math.random() gives a random real number between 0.0 and 6.0, and 1.0+6.0*Math.random() gives a random real number between 1.0 and 7.0. Java's Math class also contains a floor which converts a real number to an integer by ignoring any value after the decimal point (i.e., by rounding down). Applying this to the previous expression gives floor(1.0 + 6.0*Math.random()), which is an expression which gives random integers between 1 and 6.
(Technical point: The previous expression could give 7 if Math.random() were exactly 1. However, for typical random number generators, Math.random() will not give exactly 1.0, although it can give 0.0. Thus, floor(1.0 + 6.0*Math.random()) can never give 7 -- only integers 1, 2, 3, 4, 5, 6.)
import java.lang.Math; ... public static int roll () { return ((int)Math.floor(1.0 + 6.0*Math.random())); }
Rolling 2's: Write a program that reads an integer N, rolls a die N times, counts the number of times a 2 is thrown, and the fraction of the rolls that are 2's.
Rolling a 2: Write a (static) method getATwo that returns the number of rolls of a die until a 2 is thrown.
Write a program that calls getATwo 100 times, and computes the minimum, maximum, and average number of rolls needed to roll a 2.
Modify the program in part a to get a program that calls getATwo 1000 times and records, in an array of large enough size (perhaps 100), the number of times a 2 is obtained in 1 roll, in 2 rolls, in 3 rolls, etc. The program should then print the frequency of the number of rolls in a table, such as the following:
Number Frequency of Rolls Count 2 138 3 116 4 ...
If these data were received, one would conclude that a 2 was rolled on the second roll for 138 of the 1000 experiments, while a 2 was rolled (for the first time) on the third roll in 116 experiments. Et cetera.
Rolling Two in a Row: Write a program that rolls a die 1000 times and counts the number of times the same result occurs twice in a row. In your counting, you should consider a sequence 3 3 3 as containing two sets of identical rolls -- the middle 3 matches the first, and the third 3 matches the second. Thus, the following sequence of rolls would be counted as having the same result occur twice in a row for 4 times.
1 5 3 2 4 4 6 5 5 5 3 6 2 1 1 2
Rolling a Pair of Dice: Write a method pairOfDice that rolls a pair of die and returns their sum. Use this method in a program that computes the number of times a 2, 3, 4, ..., 11, 12 are rolled in 1000 experiments. Show your results in a table.
This document is available on the World Wide Web as
http://www.math.grin.edu/~walker/courses/153.sp00/lab-iteration-arrays.html
created April 18, 2000 by Henry M. Walker