REPETITION - RECURSION


1. OVERVIEW

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:

  1. A base case where the recursion stops and begins to unwind
  2. A recursive step where the function calls itself.

2. EXAMPLE PROBLEM DECIMAL TO BINARY CONVERSION


2.1 Requirements

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.


2.2 Design

A top down analysis of the problem is given below.

TOP DOWN ANALYSIS

We will implement this using the following procedures:

  1. DECIMAL_2_BINARY (top level procedure): Input decimal number, call CONVERT.
    NAMEDESCRIPTIONTYPERANGE
    NATURAL_NUMBERGlobal input variableNATURALDefault
  2. CONVERT (Level 2 procedure): Convert to binary and output result. Call to PAD_WITH_ZEROES when necessary.
    NAMEDESCRIPTIONTYPERANGE
    DECL_NUM Formal parameterNATURALDefault
    DIGIT_COUNTERFormal parameterNATURALDefault
  3. PAD_WITH_ZEROES (Level 3 procedure): Pad output with appropriate number of zeroes.
    NAMEDESCRIPTIONTYPERANGE
    DIG_COUNTFormal parameterNATURALDefault
    END_VALUELocal variableINTEGERDefault

An appropriate Nassi Shneiderman design is given below.

NASSI_SHNEIDERMAN CHART

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.

FLOW CHART

2.3. Implementation

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;

2.4. Testing

2.4.1. Black box testing

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 CASEEXPECTED RESULT
DECIMAL_NUMBEROUTPUT
-1CONSTRAINT_ERROR
000000000 00000000 00000000 00000000
100000000 00000000 00000000 00000001
107374182300111111 11111111 11111111 11111111
214748364601111111 11111111 11111111 11111110
214748364701111111 11111111 11111111 11111111
2147483648DATA_ERROR

2.4.2. White box testing

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.

2.4.2. Data validation testing

This should also be done.


Example Problem Decimal to Binary Conversion Report.


3. EXAMPLE PROBLEM FIBONACCI


3.1 Requirements

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.


3.2 Design

A top down analysis of the problem is given below.

TOP DOWN ANALYSIS

The above can be implemented using the following procedures/functions

  1. FIBONACCI_TERM (Level 2 function): Calculate and return term.
    NAMEDESCRIPTIONTYPERANGE
    TERM_NUMFormal_parameterPOSITIVEDefault
  2. FIBONACCI (Top level procedure): Input required term, call FIBONACCI_TERM, output result.
    NAMEDESCRIPTIONTYPERANGE
    TERM_NUMFormal_parameterPOSITIVEDefault

Nassi-Shneiderman designs for the above are given below.

NASSI_SHNEIDERMAN CHART

3.3. Implementation

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;

3.4. Testing

3.4.1. Black box testing

TEST CASEEXPECTED RESULT
TERM_NUMBEROUTPUT
0CONSTRAINT_ERROR
10
21
29?
30?
31CONSTRAINT_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.

3.4.2. White box testing

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