Recursion is a mechanism whereby repetition can be achieved using (at its simplest) a procedure or function that continuous to call itself until some base case is reached. We say that a recursive algorithm winds up until the base case is reached and then unwinds. Note that during the unwinding process further program statements may be called. Thus a recursive algorithm requires:
Develop and implement some Ada software which, when given a natural decimal number, will convert this integer into a binary number. For example, given the number 41 we would expect the system to output:
00000000 00000000 00000000 00101001
The standard mechanism, for converting from decimal to binary is to repeatedly divide the decimal number by 2 and, at each division, output the remainder (0 or 1). An example is given to the right where the binary number 101001 is derived from the decimal number 41.
A top down analysis of the problem is given below.
We will implement this using the following procedures:
| NAME | DESCRIPTION | TYPE | RANGE | 
|---|---|---|---|
| NATURAL_NUMBER | Global input variable | NATURAL | Default | 
| NAME | DESCRIPTION | TYPE | RANGE | 
|---|---|---|---|
| DECL_NUM | Formal parameter | NATURAL | Default | 
| DIGIT_COUNTER | Formal parameter | NATURAL | Default | 
| NAME | DESCRIPTION | TYPE | RANGE | 
|---|---|---|---|
| DIG_COUNT | Formal parameter | NATURAL | Default | 
| END_VALUE | Local variable | INTEGER | Default | 
An appropriate Nassi Shneiderman design is given below.
Here we have used a recursive algorithm to ensure that the binary digits are output in the correct order. If we used a simple while loop the reverse result would be produced. A flow chart indicating the overall flow of control through the proposed software is given below.
The encoding of the above design is as follows:
-- DECIMAL 2 BINARY
-- 17 September 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool
with TEXT_IO;
use TEXT_IO;
procedure DECIMAL_2_BINARY is
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    DECIMAL_NUMBER: NATURAL;
    ---------------------------------------------------------------------------
    -- CONVERT
    procedure CONVERT(DEC_NUM, DIGIT_COUNTER: INTEGER) is
        -----------------------------------------------------------------------
        -- PAD WITH ZEROES
        procedure PAD_WITH_ZEROES(DIG_COUNT: NATURAL) is
            END_VALUE: INTEGER;
        begin
            END_VALUE := 32-DIG_COUNT;
            for LOOP_PARAMETER in 1..END_VALUE loop
                PUT("0");
                if (LOOP_PARAMETER rem 8 = 0) then
                    PUT(" ");
                end if;
            end loop;
        end PAD_WITH_ZEROES;
        -----------------------------------------------------------------------
    begin
    -- Output digits and spaces between bytes when appropriate
        if DEC_NUM /= 0 then;
            CONVERT(DEC_NUM/2, DIGIT_COUNTER+1);
            PUT(DEC_NUM rem 2, WIDTH=>1);
            if (LOOP_PARAMETER rem 8 = 0) then
                PUT(" ");
            end if;
        else
            PAD_WITH_ZEROES(DIGIT_COUNTER);
        end if;
    end CONVERT;
    ---------------------------------------------------------------------------
-- TOP LEVEL
begin
    PUT("Input a natural integer: ");
    GET(DECIMAL_NUMBER);
    NEW_LINE;
    PUT(DECIMAL NUMBER)
    PUT(" = ");
    CONVERT(DECIMAL_NUMBER,0);
    NEW_LINE;
end DECIMAL_2_BINARY;
BVA, Limit and Arithmetic testing: Use BVA testing to analyse nature of inputs. Limit testing to test operation of the software at the limits, and arithmetic te sting to test the arithmetic expressions. A suggested set of test cases is given in the following Table.
| TEST CASE | EXPECTED RESULT | 
|---|---|
| DECIMAL_NUMBER | OUTPUT | 
| -1 | CONSTRAINT_ERROR | 
| 0 | 00000000 00000000 00000000 00000000 | 
| 1 | 00000000 00000000 00000000 00000001 | 
| 1073741823 | 00111111 11111111 11111111 11111111 | 
| 2147483646 | 01111111 11111111 11111111 11111110 | 
| 2147483647 | 01111111 11111111 11111111 11111111 | 
| 2147483648 | DATA_ERROR | 
Path testing: We should test all paths identified in the flow charts given in Tables 3 and 4. This is already achieved by the above test cases.
Loop testing: The loop is a variable count loop therefore we should test the the loop with 1, 2 and some other number of passes through the loop. Again this will be achieved by the test cases given above.
This should also be done.
Example Problem Decimal to Binary Conversion Report.
Design and Produce some software, written in Ada, that outputs the Nth term in a Fibonacci Sequence:
0, 1, 1, 2, 3, 5, 8, 13 ....
where the first two, terms are 0 and 1 , and each term thereafter is the sum of the two proceeding terms. Thus:
Fib(N) = Fib(N-1) + fib(N-2)
where N is greater than 2. Assume that the N is a positive integer in the range 1..30 inclusive.
A top down analysis of the problem is given below.
The above can be implemented using the following procedures/functions
| NAME | DESCRIPTION | TYPE | RANGE | 
|---|---|---|---|
| TERM_NUM | Formal_parameter | POSITIVE | Default | 
| NAME | DESCRIPTION | TYPE | RANGE | 
|---|---|---|---|
| TERM_NUM | Formal_parameter | POSITIVE | Default | 
Nassi-Shneiderman designs for the above are given below.
The encoding of the above design is as follows:
-- FIBONACCI
-- 17 September 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool
with TEXT_IO;
use TEXT_IO;
procedure FIBONACCI is
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    TERM_NUMBER: POSITIVE range 1..30;
    -----------------------------------------------------------------------
    -- FIBONACCI
    function FIBONACCI_TERM(TERM_NUM: POSITIVE) return INTEGER is
    begin
    case TERM_NUM is
        when 1 =>
        return 0;
        when 2 =>
        return 1;
        when others =>
        return FIBONACCI_TERM(TERM_NUM-1) +
            FIBONACCI_TERM(TERM_NUM-2);
    end case;
    end FIBONACCI_TERM;
    -----------------------------------------------------------------------
-- TOP LEVEL PROCEDURE
BEGIN
-- Input required term number
    PUT_LINE("Input term  number (positive integer 1..30): ");
    GET(TERM_NUMBER);
-- Calculate and output term
    PUT("Fib(");
    PUT(TERM_NUMBER, WIDTH=>1);
    PUT(") = ");
    PUT(FIBONACCI_TERM(TERM_NUMBER));
    NEW_LINE;
end FIBONACCI;
| TEST CASE | EXPECTED RESULT | 
|---|---|
| TERM_NUMBER | OUTPUT | 
| 0 | CONSTRAINT_ERROR | 
| 1 | 0 | 
| 2 | 1 | 
| 29 | ? | 
| 30 | ? | 
| 31 | CONSTRAINT_ERROR | 
BVA, Limit and Arithmetic Testing. Test range and limits for TERM_NUMBER input variable and arithmetic expressions using test cases of the form presented in the table right.
Path testing: Test all paths through FIBONACCI_TERM function. This is adequately achieved by the set of test cases presented above right.
Note: no loop testing will be required although we should carry out some data validation tests.
Example Problem Fibonacci Report.
Created and maintained by Frans Coenen. Last updated 11 October 1999