INTRODUCTION TO PROGRAMMING IN JAVA: REPETITION ("WHILE" LOOPS AND THE BREAK STATEMENT)

NOTE: This set of www pages is not the set of www pages for the curent version of COMP101. The pages are from a previous version that, at the request of students, I have kept on line.


CONTENTS

1. The Java "while" loop construct
2. Example problem - Euler's number
2.1. Requirements
2.2. Analysis
2.3. Design
 
2.4. Implementation
2.5. Testing
3. While loop or for loop?
4. Continuous loops and the break statement
5. Missing control expressions in "for" loops



1. THE JAVA "WHILE" LOOP CONSTRUCT

The "while" loop construct is traditionally used to implement variable count loops (although, in Java, this can also be achieved with a "for" loop) which are therefore often referred to as while loops. (As we will see while loops can also be used to implement fixed count loops --- but more of this later.) A variable count loop is used when the number of iterations associated with a loop construct is not known in advance. What is known, however, is that it should continue provided a certain condition is true. When the condition becomes false, the repetition stops. The Java while loop statement has the following format:

 
< Start expression >

...

while ( < Test expression > ) {
        < sequence of statements 
	including update expression >        
	}

The "Test expression" is used to test a loop control variable. When the expression evaluates to false the loop terminates. So that the loop has a "chance" of terminating the control variable must be "updated" on each iteration. Note that the loop control variable is initialised somewhere before commencement of the construct (the "start expression").



2. EXAMPLE PROBLEM EULER'S NUMBER


2.1 Requirements

Design, develop and produce a Java program that calculates an approximation, accurate to five decimal places, of Euler's number e (as used in the exponential function, natural logarithms, Etc.), using the infinite series:

e = 1 + {1/1!} + {1/2!} +  {1/3!} +  {1/4!} + ...
  = 1 + {1/1}  + {1/2}  +  {1/6}  +  {1/24} + ...
  = 1 +   1    +  0.5   + 0.16666 + 0.04166 + ...

Thus the first element in the series is 1 after which each subsequent value is equivalent to the previous value divided by N-1, where N is the current element number:

e = 1 + {1/(2-1)} + {1/(3-1)} + {0.5/(4-1)} + {0.16666/(5-1)} + ...
  = 1 +   {1/1}   +   {1/2}   +   {0.5/3}   +  {0.16666/4}   + ...
  = 1 +     1     +    0.5    +   0.16666   +    0.04166      + ...

Output should comprise: (a) a list of terms, (b) the number of terms and (c) the approximation.


2.2 Analysis

The series has an infinite number of decreasing terms. However, the approximation is only required to be accurate to five decimal places therefore we can ignore any term with a value of less than 0.000001. But, we do not know (without doing the calculation) how many iterations will be required, therefore a variable count loop suggests itself. We can implement the solution using a simple application program comprising only a main method containing a "while" loop.


2.3 Design

2.3.1 Euler Class

Method Summary
public static void main(String[] args)
           Main method to calculate the approximation using a while loop. We start with the first term (1) and initialise the loop counter to 1 to find the second term; and then keep incrementing the loop counter and iterating until a term which is less than 0.000001 is reached.

A Nassi-shneiderman chart for the above main method is given in Figure 1. This is still a pre-test loop and thus is incorporated into the chart in the same way that a for loop would be.

 

NASSI-SHNEIDERMAN CHART FOR EULER'S NUMBER APPROXIMATION
	METHOD

Figure 1: Nassi-Shneiderman charts for Euler's number approximation method


2.4 Implementation

// EULER'S NUMBER APROXIMATION CLASS
// Frans Coenen
// Wednesday 14 April 1999
// Revised Friday 9 January 2004, Wednesday 23 August 2005
// The University of Liverpool, UK

class Euler {

    // ------------------ METHODDS -----------------------
    
    /* Main method  */

    public static void main(String[] args) {
    	final double LIMIT     = 0.000001;
        double termValue       = 1.0;
        double estimationFor_e = 1.0;
        int termNumber         = 1;
	
	// Calculation
	
	while(termValue>LIMIT) {       
	    System.out.printf("%.5f\t",termValue);
	    termValue = termValue/(double) termNumber;
      	    estimationFor_e = estimationFor_e + termValue;
            termNumber++;
	    }
    
    	// Output
	
	System.out.println("\nNumber of terms = " + (termNumber-1));
        System.out.printf("Approximation   = %.5f\n",estimationFor_e);
     	}
    }

Table 1: Euler's number approximation program


2.5 Testing

The code cannot be influenced by a user therefore a simple run through will be appropriate. The result will be of the form shown below.

$ java Euler
1.00000 1.00000 0.50000 0.16667 0.04167 0.00833 0.00139 0.00020 0.00002 0.00000
Number of terms = 10
Approximation   = 2.71828



3. WHILE LOOP OR FOR LOOP?

The above code could equally well have been implemented using a Java "for" loop as shown in Table 2. Similarly the "Smiley" face program described earlier can be implemented using a "while" loop (Table 3).

So when should we use a "for" loop and when a "while" loop --- both are pre-test loops and both can be used for fixed and variable count loops? This is not a problem in languages where "for" loops can only be used to describe fixed count loops (e.g. Ada, Pascal, BASIC), the answer is:

 
"For" statements for fixed count loops.
"While" statements for variable count loops.

In Java where for and while statements can be used to describe both fixed and variable count loops, it is simply a matter of personal choice!

// EULER'S NUMBER APROXIMATION CLASS
// Frans Coenen
// Wednesday 14 April 1999
// Revised Wednesday 23 August 2005
// The University of Liverpool, UK

class EulerVer2 {

    // ------------------ METHODDS -----------------------
    
    /* Main method  */

    public static void main(String[] args) {
    	final double LIMIT     = 0.000001;
	final int START_VALUE  = 1;	
        double termValue       = 1.0;
        double estimationFor_e = 1.0;
	int termNumber         = START_VALUE;
	
	// Calculation
	
	for( ;termValue>LIMIT;termNumber++) {        
	    System.out.printf("%.5f\t",termValue);
	    termValue  = termValue/(double) termNumber;
            estimationFor_e = estimationFor_e + termValue;
	    }
	    
    	// Output
	
	System.out.println("\nNumber of terms = " + (termNumber-1));
        System.out.printf("Approximation   = %.5f\n",estimationFor_e);
     	}
    }

Table 2: Euler's number program
implemented using a for loop

// SMILEY FACE APPLICATION CLASS
// Frans Coenen
// Tuesday 13 April 1999
// The University of Liverpool, UK
   
class SmileyFace {
 
    // ------------ METHODS -----------------
    
    /* Main method  */

    public static void main(String[] args) {	
        int       loopParameter = 0;
	final int END_CONDITION = 10;
	
	// While loop
	
	while (loopParameter < END_CONDITION) {
	    System.out.print("(-:\t");
	    loopParameter++;
	    }
	    
	// End
	
	System.out.println("\n");
	}
    }

Table 3: Smiley face program implemented using a while loop




4. CONTINUOUS LOOPS AND THE BREAK STATEMENT

Sometimes there is a need to terminate a loop somewhere in the middle. Many programming languages therefore support a break statement --- including Java. This has already been introduced in connection with switch statements, but can also be used to "break out" of a loop.

Wherever possible "loop break" statements should be avoided as they alter the flow of control associated with loop statements from a clear "in at the top" to "out at the bottom" to something which is less obvious. In Java a break statement can sometimes "legitimately" be used to "break out" of a continuous loop. However, in most cases there is an alternative strategy that will avoid the use of a break.

In Java we may write continuous loops using a for statement thus:

for ( ; ;) {
    < STATEMENTS TO BE REPEATED INDEFINITELY >
    }

or a while statement:

while (true) {
    < STATEMENTS TO BE REPEATED 
	INDEFINITELY >
    }
 

(Note that the test exoression is the Boolean value true here which always succeeds, i.e. evaluates to "true".) Continuous loops are sometimes used when awaiting a particular input which is tested for on each iteration. If found a break statement may then be used to break out of the loop:

if ( < SOME CONDITION > ) break;

Consider the menu example application program described previously. This included a method that displayed a menu and allowed the user to enter a menu option, and another method to process the selected option using a switch statement which incorporated an error recovery mechanism in the event of an erroneous user input. An alternative implementation might be to use a continuous loop which kept repeating until a correct selector was input. This is illustrated in Table 4. On each iteration of this loop a test is made (using an "if" construct) to check the input, and if appropriate to "jump" out of the loop using a break statement.

// MENU INTERFACE EXAMPLE APPLICATION
// Frans Coenen
// Thursday 15 April 1999
// Revised: Tuesday 26 July 2005
// The University of Liverpool, UK   

import java.util.*;

class MenuInterfaceEx2App {

    // ------------------- FIELDS ------------------------ 
        
    // Create Scanner class instance

    private static Scanner input = new Scanner(System.in);
    
    // ------------------ METHODS ------------------------  
    
    /* Main method */
    
    public static void main(String[] args) {
        // Output menu
        int selector = outputMenu();

        // Process selection
        processSelector(selector);
        }

    /* Outpur menu */

    private static int outputMenu() {
        int selector = 0;
        
	while (selector < 1 || selector > 4) {
    	    System.out.println("PROGRAMMING PARADIGMS");
	    System.out.println("=====================");
	    System.out.println("1. Imperative");
	    System.out.println("2. Object oriented");
	    System.out.println("3. Logic");
	    System.out.println("4. Functional");
	    System.out.println("Select option: ");
	    selector = input.nextInt();
	    }
	    
	// Return
	return(selector);    
	}

    /* Process selector. If unrecognised selection output error message and 
    repeat. */
	
    private static void processSelector(int selector) {	
	switch (selector) {
	    case 1:
	        System.out.println("Example languages include C, Ada and " +
			"Pascal");
		break;
	    case 2:
	        System.out.println("Example languages include Java, Eiffel " +
			" and C++");
		break;
	    case 3:
                System.out.println("Example languages include Prolog");
		break;
	    case 4:
                System.out.println("Example languages include Lisp and " +
			" Miranda");
		break;
            default:
                System.out.println("ERROR: Unrecognised error in switch " +
			" statement");
	    }
        }
    }

Table 4: Alternative implementation for menu interface example program

As noted above there is usually an appropriate alternative that avoids the need for a break statement. This is true in the case of the menu example in that we could have written the method as follows:

/* Output menu */

private static int outputMenu() {
    int selector = 0;
        
    while (selector < 1 || selector > 4) {
    	System.out.println("PROGRAMMING PARADIGMS");
	System.out.println("=====================");
	System.out.println("1. Imperative");
	System.out.println("2. Object oriented");
	System.out.println("3. Logic");
	System.out.println("4. Functional");
	System.out.println("Select option: ");
	selector = input.nextInt();
	}
	   
    // Return
    return(selector);
    }

In the above code we have used a variable count while loop which repeats until an appropriate selection is made (the selector doubles up as the loop control parameter). Note that because we are using a pretest loop construct we must initialise the selector with a value that is outside of the required range of 1 to 5 inclusive. An alternative loop construct, which would not require such an initialisation, is a post test loop where we test the user's input at the end of each iteration (more on this later).




5. MISSING CONTROL EXPRESSIONS IN "FOR" LOOPS

Although a for loop usually comprises (1) a "start expression" to initialise the loop control variable, (2) a "test expression" to determined whether to continue the loop or not, and (3) an "update expression" to incremented/decremented the control variable. It is not necessary to include all or any of these. Some examples are presented in the code given in Table 5.

The code given in Table 5 contains four "for" loops. The first uses the standard format with all expressions present and produces the result of adding up the sequence {1, 2, 3, 4, 5, 6, 7, 8, 9}. The second has no "start expression" as an existing data item, total, instantiated on the previous loop, is used. The loop is used to count down from 45 to 5 in steps of five.

 

The third loop has no "test expression" as this is included within the loop statements. It produces a sequence where each element is produced by adding the loopCounter to the previous element in the sequence starting with the value of the data item total as set by the previous loop. Note the use of the break statement to jump out of the loop when the sequence gets to above 50! The last loop has no "update expression", this is included within the body of the loop statement. The resulting output is presented in Table 6.

As noted above if we omit all the expressions a continuous loop effect is produced. For example:

for ( ; ; ) 
    System.out.println("This loop will " +
             ("go on for ever");

Note that we still have to include the semicolon separators.

// FOR LOOP EXAMPLE APPLICATION
// Frans Coenen
// Wednesday 24 March 1999
// Revised Thursday 15 January 2004
// The University of Liverpool, UK
      
class ForLoopsExampleApp {

    // ---------------- FIELDS -----------------	
    
    /* NONE */
    
    // --------------- METHODS ------------------

    /** MAIN METHOD: */
    
    public static void main(String[] args) {
    	// Normal for loop to determine total. 
	int total = normalLoop();
	// No start expression (start condition) 
    	total = noLoopCountInitExp(total);
    	// No test expression (end condition)
	noExitContExp(total);
    	// No update expression 		
        noIncContExp();
	}
    
    /* Normal for loop to determine total. */
    
    public static int normalLoop() {
    	int total = 0;
	final int START_LOOP=1, END_LOOP=10;
	
	System.out.print("Loop 1 (total): ");
    	for (int loopCounter=START_LOOP;loopCounter < END_LOOP;loopCounter++) 
    	    	total=total+loopCounter;
	    	
    	System.out.println("Total = " + total + "\n");
	return(total);
    	}
	
    /* No loop counter initialisation expression */
    
    public static int noLoopCountInitExp(int total) {
    	final int DECREMENT=5, MIN_TOTAL=0;
    	System.out.print("Loop 2 (A.P.): ");
    	for(;total>MIN_TOTAL;total=total-DECREMENT) 
			System.out.print(total + " ");
    	System.out.println("\n");
	return(total);
        }	
    
    /* No exit condition expression (variable count loop) */
    
    public static void noExitContExp(int total) {
    	final int START_LOOP=1, MAX_TOTAL=50;
	
	System.out.print("Loop 3 (G.P.): ");
	for (int loopCounter=START_LOOP;;loopCounter++) {
    	    total=total+loopCounter;
	    System.out.print(total + " ");
	    if (total > MAX_TOTAL) break;
	    }
    	System.out.println("\n");
	}
	
    /* No increment loop control expression */		
    
    public static void noIncContExp() {
    	int increment=1, total;    
   	final int START_TOTAL=0, MAX_TOTAL=50, MULTIPLIER=2;
	
	System.out.print("Loop 4 (another total): ");    
    	for (total=START_TOTAL;total < MAX_TOTAL;) {
    	    total=total+increment;
	    increment=increment*MULTIPLIER;
	    }	 
    	System.out.println("Total = " + total + "\n");	
    	}
    }

Table 5: For loops with missing expressions

$ java ForLoopsExampleApp
Loop 1 (total): Total = 45

Loop 2 (A.P.): 45 40 35 30 25 20 15 10 5

Loop 3 (G.P.): 1 3 6 10 15 21 28 36 45 55

Loop 4 (another total): Total = 63

Table 6: Output from for loops example with missing expressions




Created and maintained by Frans Coenen. Last updated 10 February 2015