Looping Review and the Iterative/Counting Loop

We have seen two types of loops so far:

The pretest loop.  This is where the condition necessary to continue looping is checked before the instructions within the loop are executed.

In FORTRAN 90, we implement such a loop with the DO WHILE construct.

The post-test loop. This loop places the condition at the end of the loop and if the condition is true the keyword EXIT is used to stop the looping.

The traditional FORTRAN DO loop is used in the post-test loop and an IF statement with an EXIT command is used to stop the looping.

Why use loops? 

One Good Use: Input Validation.

There will be many times in which we wish to "force" the user to enter acceptable data.

For example, write a program that computers the factorial (N!) of a given number (N).

        INTEGER :: input = 0
        INTEGER :: counter = 1
        INTEGER :: factorial = 1

        WRITE(*,*) "Enter a value to compute N! : "
        READ(*,*) input

        DO WHILE (counter <= input)
                factorial = factorial * counter
                counter = counter + 1
        END DO

        WRITE(*,*) input, "!  = ", factorial

The program above will record all values less than or equal to zero as having a factorial value of 1.

We can implement this fix with either a pretest or post-test loop!

Pretest

        DO WHILE(input < 1)
                WRITE(*,*) "Enter a value to compute N! : "
                READ(*,*) input
        END DO
Post-test
        DO
                WRITE(*,*) "Enter a value to compute N! : "
                READ(*,*) input

                IF(input > 0) EXIT

        END DO

Another Good Use of Loops:  Counting

The program below will do a simple WRITE statement the number of times requested by the user.

PROGRAM printtimes

IMPLICIT NONE

        INTEGER :: num_print
        INTEGER :: count = 0

        WRITE(*,*) "Please enter the number of times to print: "
        READ(*,*) num_print

        DO WHILE (count < num_print)
                WRITE(*,*) "Welcome to FORTRAN!! ", count+1
                count = count + 1
        END DO

END PROGRAM printtimes
Pretest DO with EXIT equivalent loop
        DO
                IF (count >= num_print) EXIT
                WRITE(*,*) "Welcome to FORTRAN!! ", count+1
                count = count + 1
        END DO

4.1.3 The Iterative or Counting Loop

The iterative DO loop will work similarly to the other loops we have seen so far, but the syntax is a little more concise and this type of loop is the most commonly used looping structure.

The iterative DO loop has the form:

	DO counter = start, end, step
		BODY OF LOOP
	END DO

Example:  Write a program that prints the "Welcome to FORTRAN" message as many times as requested by the user.  Use input validation to force the input to be a number greater than or equal to 1 and use an iterative Do loop.

 Enter the number of times to print:
-1
 Enter the number of times to print:
0
 Enter the number of times to print:
4
 Welcome to FORTRAN!!  1
 Welcome to FORTRAN!!  2
 Welcome to FORTRAN!!  3
 Welcome to FORTRAN!!  4

One Possible Solution:

PROGRAM itdo

IMPLICIT NONE

        INTEGER ::  count
        INTEGER ::  num_print

        DO
                WRITE(*,*) "Enter the number of times to print: "
                READ(*,*) num_print
                IF(num_print > 0) EXIT
        END DO

        DO count = 0, num_print - 1, 1
                WRITE(*,*) "Welcome to FORTRAN!! ", count+1
        END DO

END PROGRAM itdo

The step can also be negative!

 Enter the number of times to print:
13
 Welcome to FORTRAN!!  13
 Welcome to FORTRAN!!  12
 Welcome to FORTRAN!!  11
 Welcome to FORTRAN!!  10
 Welcome to FORTRAN!!  9
 Welcome to FORTRAN!!  8
 Welcome to FORTRAN!!  7
 Welcome to FORTRAN!!  6
 Welcome to FORTRAN!!  5
 Welcome to FORTRAN!!  4
 Welcome to FORTRAN!!  3
 Welcome to FORTRAN!!  2
 Welcome to FORTRAN!!  1

New Iterative Do Loop

        DO count = num_print,  1, -1
                WRITE(*,*) "Welcome to FORTRAN!! ", count
        END DO

How about a step of two?

 Enter the number of times to print:
10
 Welcome to FORTRAN!!  1
 Welcome to FORTRAN!!  3
 Welcome to FORTRAN!!  5
 Welcome to FORTRAN!!  7
 Welcome to FORTRAN!!  9
 Welcome to FORTRAN!!  11
 Welcome to FORTRAN!!  13
 Welcome to FORTRAN!!  15
 Welcome to FORTRAN!!  17
 Welcome to FORTRAN!!  19
New Iterative Do Loop
        DO count = 1, num_print*2, 2
                WRITE(*,*) "Welcome to FORTRAN!! ", count
        END DO

Question, can you change the value of the loop counter variable?  In the example above, can we alter the value of count?

        DO count = 1, num_print*2, 2
                count = count + 1
                WRITE(*,*) "Welcome to FORTRAN!! ", count
        END DO
And the answer is... an error...
        
                count = count + 1
                ^
"itdo4.f90", Line = 15, Column = 3: ERROR: The DO variable must not be defined while it is active.

Problem:

Euler's number, e, is used as the base of natural logs.  It can be approximated using the formula:

e = 1 + 1/1! + 1/2! + ... + 1/(n-1)! + 1/n!

Write a program that accepts a value for n and calculates the corresponding value of e.

Solution:

PROGRAM est_e

IMPLICIT NONE

        INTEGER :: n            !NUMBER INPUT BY USER
        INTEGER :: factorial = 1  !VALUE OF FACTORIAL FOR DENOMINATOR
        REAL :: este = 1.0      !THE ESTIMATE OF e
        INTEGER :: lcv          !LOOP CONTROL VARIABLE

        WRITE(*,*) "Please enter a value of n: "
        READ(*,*) n

        DO lcv = 1, n, 1
                factorial = factorial * lcv
                este = este + 1/REAL(factorial)
        END DO

        WRITE(*,*) "The estimate of e is: ", este

END PROGRAM est_e

Iterative Do Loop "Rules"

  1. The values of the starting, ending, and step may be a constant, variable, or expression.
  2. If the (start * step) <= (end * step) the program executes within the body of the loop.

The number of iterations of an iterative do loop is: (end - start + step)/step

4.1.6 Nesting Loops

It is possible for one loop to be completely inside another loop!  Such is a situation results in nested loops.

PROGRAM nested

IMPLICIT NONE

        INTEGER :: i    !LCV FOR OUTER LOOP
        INTEGER :: j    !LCV FOR INNER LOOP

        DO i = 1, 3, 1
                DO j = 1, 5, 1
                        WRITE(*,*) i, " * ", j, " = ", i * j
                END DO
        END DO

END PROGRAM nested
What is happening here?

Nested Iterative Do Loops "Rules"