Java, Java, Java 3E
Chapter 6: Control Structures
In the Laboratory: Finding Prime Numbers

R. Morelli

©2006 Prentice-Hall


In the Laboratory: Finding Prime Numbers

The purpose of this lab is to provide practice using loop control structures in designing and implementing solutions to programming problems. The objectives are

Problem Statement

Suppose that Atlas Computer Security has contacted you about consulting for them to develop public key encryption software. One thing you're going to need in this software is a method that can test whether a number is a prime or not. To help demonstrate your prime number tester, the company wants you to write a Java applet that prompts the user for a positive integer and then displays all of the prime numbers less than or equal to the user's integer. If they like your demo, they will probably give you the contract for the encryption software.

GUI Specifications

The Graphical User Interface (GUI) for this applet needs a component to handle the user's input, and another component to display the prime numbers. A TextField would be an appropriate input component, because the user needs to input a single integer value. The TextField can also serve as the means by which the user indicates that an action should be taken. Whenever the user types a Return or Enter in the TextField, the program should test the TextField's current value for primality.

The output component should allow the program's output to extend over several lines. This is a perfect job for a TextArea. In addition to these components, we'll need a Label to prompt the user as to what kind of input is expected. Figure 1 provides a summary of the GUI.


  
Figure 1: The user interface for PrimesApplet.
\begin{figure}
\rule{4.75in}{.05cm}

\epsfig {file=/home/ram/java/text/ch6-loops/figures/primesscreen.eps}
\rule{4.75in}{.05cm}\end{figure}

Problem Decomposition

There are two tasks involved in the demo program. One is to provide a user interface, a GUI. The other is to provide the expertise needed to determine whether a number is prime. This suggests that we should break this problem up into two objects: a PrimesApplet object, which will manage the interface, and a Primes object, which will contain methods to determine whether a number is prime and to find prime numbers within a certain range.

Problem Design: The PrimesApplet Class

The design of PrimesApplet should be similar to that of other applets we've built. Of course, the applet must create an instance of the Primes. This is the object it will call upon to test whether numbers are prime.

In terms of its GUI elements, the applet should contain a TextField for user input and a Label for prompting the user. These components should be instantiated in the applet and added to the applet in the init() method. Because it will generate user actions, whenever the user types the Enter key, the TextField should be given an ActionListener. This should also be done in the init() method.

The algorithm used by PrimesApplet is event driven. In the init() method, the applet should be registered as the listener for ActionEvents that occur in the TextField. Then, whenever such an event occurs, Java will call the applet's actionPerformed() method, where the event should be handled. The actionPerformed() method should get the input from the TextField, convert it to an integer, and then display all of the prime numbers less than the user's number:

    1. Get the user's input from the TextField.
    2. Convert the input String into an int.
    3. Display in the TextArea all the prime numbers less than 
       the user's number.

Step 2 of this algorithm will require us to use the Integer.parseInt() method to convert a String into an int:

    int num = Integer.parseInt("564"); // Converts "564" to 564

Step 3 of this algorithm will require a loop, and it is here where the applet must call on the expertise of the Primes object. Because this step will be somewhat complex, it should be encapsulated into a separate method.

Taken together, these design decisions lead to the following specification for the PrimesApplet class:

Note that the findPrimes() method will be a private method. This is appropriate, since it is not intended to be used outside of this class.

Problem Design: The Primes Class

As our design of the PrimesApplet class suggested, the Primes should have a public method that can be used to test whether a number is prime. Let's call this method isPrime(). This should be a boolean method that should return true when its int parameter is a prime number. Otherwise it should return false.

The Primes class does not have any kind of internal state that would be represented in the form of instance variables. Any variables that it may need to determine if a number is prime can be declared within the isPrime() method. Thus, its specification is very simple:

The findPrimes() Algorithm

The findPrimes() method takes a single int parameter, N, and will display all of the prime numbers, less than or equal to N, in the applet's TextArea. Its algorithm should use a loop to test the numbers between 1 and N and display all the prime numbers in that range. Obviously, this is a counting loop, because you know exactly how many iterations it must make before entering the loop. Also, the task of determining whether an integer is prime or not will be farmed out to the Primes object. Thus, this gives us the following algorithm:

    Display "The following are the primes between 1 and N" in TextArea
    for each integer, k, the range 1 to N
        if k is prime
            display k in the TextArea

The isPrime() Algorithm

The isPrime() method should employ a loop to find whether its parameter, N, is a prime. The algorithm in this case should make use of the definition of a prime number -- that is, a number divisible only by itself and 1. It could try dividing N by K, where K is $2,3,4,5\ldots$ and so on up to N-1. If any of these numbers is a divisor of N, then N is not a prime number. If none is a divisor of N, then N is a prime number. Because the number of iterations required for this loop is not known beforehand, it will require a noncounting loop structure.

To test whether N is prime it is necessary to have an entry condition that is the conjunction of two conditions. The loop should iterate while K is less than N, and while none of the preceding values of K were divisors of N. In other words, the loop should terminate when a value K is found that evenly divides N. One way to handle this task is to use a local boolean variable as a flag  that will be raised when a value K is found that divides N:

    Initialize notDivisibleYet to true
    Initialize K to 2
    while (notDivisibleYet AND K < N)  {
        if N is divisible by K
            set notDivisibleYet to false
        increment K;
    }

This is an example of a complex loop bound . It involves the conjunction of both a count bound and a flag bound and it will terminate when either bound is reached. Thus the loop terminates when either K equals N or when N is divisible by some value of K < N.

Note that for the conjunction notDivisibleYet AND K < N to be true, both halves of it must be true. However, for it to be false, either half may be false; it is not necessary that both halves be false. In this case either notDivisibleYet will be false or $K \geq N$ will be false. This is an instance of the logic rule known as DeMorgan's Law , which can be stated as follows:

    ((P && Q) == !(P || Q))

where P and Q are simple boolean conditions.

To summarize, the above loop structure can be used in isPrime(N) to test whether N is prime. In order to decide whether N is a prime, isPrime() must check which bound actually terminated the loop, and then return the proper boolean result. If the loop terminated with K equal to N, it follows that N is prime, and isPrime() should return true. Otherwise N is not prime and it should return false.

Implementation

The implementation of this program is left to you as a lab (or programming) exercise, but here are some hints and suggestions:

Optional Refinement

As we described, public key encryption involves the use of composite numbers as well as prime numbers. A challenging extension to this lab would be to let the user type in a composite number and display its prime factorization. Design a method that takes an integer parameter and displays its prime factors in the TextArea. For example, if the user inputs 40, your method should display 40 = 2*2*2*5.



Ralph Morelli {Faculty}
12/22/1999