REPETITION - VARIABLE COUNT (WHILE) LOOPS


1. WHILE LOOPS

Variable count loops (also known as while loops) are 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 general form of a variable count loop in Ada is as follows:

while < Boolean expression > loop
        < sequence of statements >
        end loop;

5. EXAMPLE PROBLEM EULER'S NUMBER


6.1 Requirements

Design, develop and produce an Ada 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!} + ...

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.

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


5.2 Design

The series has an infinite number of 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. A top down analysis of the problem is given below.

TOP DOWN ANALYSIS

The operations identified above are trivial enough to be implemented as a single procedure incorporating a single fixed count loop.

  1. EULERS_NUMBER (Top level procedure): Calculate terms, maintain and output number of terms and maintain and output total.
    NAMEDESCRIPTIONTYPERANGE
    LIMIT Global constantFLOAT 0.000001
    TERM Global variableFLOAT Default
    TOTAL Global variableFLOAT Default
    COUNTERGlobal variableINTEGERDefualt

An appropriate Nassi-Shneiderman chart is given below.

NASSI_SHNEIDERMAN CHART

5.3. Implementation

The encoding of the above design is as follows:

-- EULER'S NUMBER
-- 16 August 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool

with TEXT_IO;
use TEXT_IO;

procedure EULERS_NUMBER is
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    package FLOAT_INOUT is new FLOAT_IO(FLOAT);
    use FLOAT_INOUT;
    LIMIT   : constant := 0.000001;
    TERM    : FLOAT   := 1.0;
    TOTAL   : FLOAT   := 1.0;
    COUNTER : INTEGER := 1;
begin
    while TERM > LIMIT loop
        PUT(TERM, FORE=>1, AFT=>5, EXP=>0);
        TERM := TERM/FLOAT(COUNTER);
        PUT(", ");
        TOTAL := TOTAL+TERM;
        COUNTER := COUNTER+1;
    end loop;
    NEW_LINE;
-- Output result
    PUT("Number of terms = ");
    PUT(COUNTER);
    NEW_LINE;
    PUT("Approximation = ");
    PUT(TOTAL, FORE=>1, AFT=>5, EXP=>0);
    NEW_LINE;
end EULERS_NUMBER;

Note that we convert the loop parameter from a integer to a float in the calculation. This conversion is temporary, lasting only until completion of the expression. Note also that we have "doctored" the end condition for the loop so that the appropriate number of loops are implemented, i.e. the value for the variable TERM (and TOTAL) has been preset to 1.0 on initialisation.


5.4. 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.

kuban-158 $ eulers_number
1.00000, 1.00000, 0.50000, 0.16667, 0.04167, 0.00833,
0.00139, 0.00020, 0.00002, 0.00000, 0.00000,
Number of terms = 11
Approximation = 2.71828

Example Problem Base Euler's Number Approximation Report.


3. WHILE LOOPS WITH EXIT

Sometimes there is a need to terminate a loop somewhere in the middle. Many imperative languages therefore support a break or exit statement. Ada actually supplies two types of exit statement:

exit;
exit when <Booleam-expression>

Wherever possible exit statements should be avoided as they alter the flow of control associated with loop statements from an clear "in at the top" to "out of the bottom" to something which is less obvious. In Ada exit statements are required where we wish to use a post test loop. Ada does not provide a specific post test loop construct and therefore, where an application necessitates the use of such a construct, we need to simulate this using an exit statement.

A typical situation where this may be required is where we have a menu interface and we we wish to include a recovery mechanism in the event of an incorrect menu selection. Consider the temperature conversion program described previously. This included the following menu interface:

-- Output Menu
        PUT_LINE("MENU OPTIONS");
        PUT_LINE("C - Centigrade to Fahrenheit conversion");
        PUT_LINE("F - Fahrenheit to Centigrade conversion");
        GET(MENU_ITEM);
-- Check menu input
        if (MENU_ITEM = 'C' OR MENU_ITEM = 'c') then
                CENT_2_FAHR;
        else
                if (MENU_ITEM = 'F' OR MENU_ITEM = 'f') then
                        FAHR_2_CENT;
                else
                        PUT("Invalid menu selection: ");
                        PUT(MENU_ITEM);
                        NEW_LINE;
                end if;
        end if;

In the event of a incorrect menu selection the program was terminated. We can include an error recovery mechanism into the program as follows:

NASSI-SHNEIDERMAN
        loop
-- Output Menu
                PUT_LINE("MENU OPTIONS");
                PUT_LINE("C - Centigrade to Fahrenheit conversion");
                PUT_LINE("F - Fahrenheit to Centigrade conversion");
                GET(MENU_ITEM);
-- Check menu input
                case MENU_ITEM is
                        when 'C' | 'c' =>
                                CENT_2_FAHR;
                                exit;
                        when 'F' | 'f' =>
                                FAHR_2_CENT;
                                exit;
                        when others =>
                                PUT("Invalid menu selection: ");
                                PUT(MENU_ITEM);
                                NEW_LINE;
                end case;
        end loop;

Note:

  1. We have introduced a cases statement to process the menu selection.
  2. The loop construct we have used:
    loop
            <Statements to be repeated>
            end loop;
    
    is known as a simple loop where the "statements to be repeated" are repeated indefinitely until some form of "interrupt" occurs. This can be either:

To write the above using a conventional while loop would require additional coding as follows:

TOP DOWN ANALYSIS
-- Output Menu
        PUT_LINE("MENU OPTIONS");
        PUT_LINE("C - Centigrade to Fahrenheit conversion");
        PUT_LINE("F - Fahrenheit to Centigrade conversion");
        GET(MENU_ITEM);
-- Check for error and repeat if necessary
        while MENU_ITEM /= 'C' and MENU_ITEM /= 'c' and MENU_ITEM /= 'F' and
                                MENU_ITEM /= 'f' loop
                PUT("Invalid menu selection: ");
                PUT(MENU_ITEM);
                NEW_LINE;
                PUT_LINE("MENU OPTIONS");
                PUT_LINE("C - Centigrade to Fahrenheit conversion");
                PUT_LINE("F - Fahrenheit to Centigrade conversion");
                GET(MENU_ITEM);
        end loop;
-- Process menu selection
        if (MENU_ITEM = 'C' OR MENU_ITEM = 'c') then
                CENT_2_FAHR;
        else
                FAHR_2_CENT;
        end if;



Created and maintained by Frans Coenen. Last updated 11 October 1999