It is sometimes desirable to process a fixed count loop backwards, i.e. in reverse. In some imperative languages this can be achieved simply by adjusting the nature of the incrementation (decrementations) and the nature of the start value. However in Ada, where we can only increment by +1 this option is not available. Instead we can include the reserved word reverse in our loop definition. For example the statement:
for NUMBER in reverse 1..5 loop PUT(NUMBER); end loop;
would produce the output:
5 4 3 2 1
Design and implement an Ada program that returns the value of N! (N Factorial) given a specific value for N. Note:
n! = n x (n-1) x (n-2) ... 3 x 2 x 1
For example:
10!= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 = 3628800
Note also that N must be a positive integer and assume that the maximum permissible value for N is 12.
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 |
---|---|---|---|
NUMBER_OF_TERMS | Global input variable | POSITIVE | 1..12 |
PRODUCT | Global variable | POSITIVE | Default |
So as to adhere to the generally accepted mathematical definition of factorial(N) we will process the loop in reverse. An appropriate Nassi-Shneiderman chart is given to the right.
The encoding of the above design is as follows:
-- FACTORIAL -- 15 September 1997 -- Frans Coenen -- Dept Computer Science, University of Liverpool with TEXT_IO; use TEXT_IO; procedure FACTORIAL is package INTEGER_INOUT is new INTEGER_IO(INTEGER); use INTEGER_INOUT; NUMBER_OF_TERMS : POSITIVE range 1..12; PRODUCT : POSITIVE; begin -- Input N_VALUE PUT_LINE("Input number of terms (integer 1..12): "); GET(NUMBER_OF_TERMS); PRODUCT := NUMBER_OF_TERMS; -- For loop for COUNTER in reverse 1..NUMBER_OF_TERMS-1 loop PRODUCT := PRODUCT*COUNTER; end loop; -- Output result PUT(NUMBER_OF_TERMS); PUT("! = "); PUT(PRODUCT); NEW_LINE; end FACTORIAL;
BVA, Limit and Arithmetic Testing. A suitable set of test cases is given in the table below.
TEST CASE | EXPECTED RESULT |
---|---|
NUMBER_OF_TERMS | OUTPUT |
0 | CONSTRAINT_ERROR |
1 | 1 |
2 | 2 |
6 | 720 |
11 | 39916800 |
12 | 479001600 |
13 | CONSTRAINT_ERROR |
Loop testing. Test repetitions in fixed count loop using set of test cases of the form given below. Note that, except for the third test case ("two passes through loop") all these have been run as either BVA, limit or arithmetic test cases (see above).
TEST CASE | EXPECTED RESULT |
---|---|
NUMBER_OF_TERMS | OUTPUT |
1 (no passes through loop) | 1 |
2 (one pass) | 2 |
3 (two passes) | 6 |
6 | 720 |
11 (end value -1 passes) | 39916800 |
12 (end value passes) | 479001600 |
Example Problem Factorial Report.
A well engineered piece of software should make efficient use of critical resources, particularly:
However, efficiency concerns should not generally override the need for clarity, readability and correctness.
Code efficiency is generally measured in terms of the number of machine statements that need to be processed. Note that:
For most computers memory restrictions are a thing of the past. This is not the case for embedded systems.
Created and maintained by Frans Coenen. Last updated 11 October 1999