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;
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.
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.
The operations identified above are trivial enough to be implemented as a single procedure incorporating a single fixed count loop.
NAME | DESCRIPTION | TYPE | RANGE |
---|---|---|---|
LIMIT | Global constant | FLOAT | 0.000001 |
TERM | Global variable | FLOAT | Default |
TOTAL | Global variable | FLOAT | Default |
COUNTER | Global variable | INTEGER | Defualt |
An appropriate Nassi-Shneiderman chart is given below.
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.
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.
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:
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:
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:
-- 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