Repetitive Execution

Select the topics you wish to review:

Repetitive Execution

Counting DO-LoopProgramming Examples:

Counting Positive and Negative Input Values

Computing Arithmetic, Geometric and Harmonic Means

Computing Factorial

General DO-Loop with EXITProgramming Examples:

Determining the Minimum and Maximum of Input Data

Computing the Square Root of a Positive Number

Computing EXP(x)

Computing the Greatest Common Divisor of Two Positive Integers

Checking If a Positive Integer Is a Prime Number

Nested DO-LoopProgramming Examples:

Computing Classes Averages

Computing a Set of Values of EXP(x)

Armstrong Numbers

Finding All Primes in the Range of 2 and N

Finding all Prime factors of a Positive Integer

Handling End of File: the READ Statement Revisited

Computing Arithmetic, Geometric and Harmonic Means: Revisited

The DO-CYCLE Construct and a Programming Example (Optional)

Download my course overheads

Counting DO-Loop

There are two forms of loops, the counting loop and the general loop. The syntax of the counting loop is the following:

DO control-var = initial-value, final-value, [step-size]

statements

END DO

where control-var is an INTEGER variable, initial-value and final-value are two INTEGER expressions, and step-size is also an INTEGER expression whose value cannot be zero. Note that step-size is optional. If it is omitted, the default value is 1. statements is a sequence of statements and is usually referred to as the body of the DO-loop. You can use any executable statement within a DO-loop, including IF-THEN-ELSE-END IF and even another DO-loop.

The following are a few simple examples:

  • INTEGER variables Counter, Init, Final and Step are control-var, initial-value, final-value and step-size, respectively.

INTEGER :: Counter, Init, Final, Step

READ(*,*) Init, Final, Step

DO Counter = Init, Final, Step

.....

END DO

  • INTEGER variables i is the control-var. The initial-value and final-value are computed as the results of INTEGER expressions Upper-Lower and Upper+Lower, respectively. Since step-size is omitted, it is assumed to be 1.

INTEGER :: i, Lower, Upper

Lower = ....

Upper = ....

DO i = Upper - Lower, Upper + Lower

.....

END DO

The meaning of this counting-loop goes as follows:

  • Before the DO-loop starts, the values of initial-value, final-value and step-size are computed exactly once. More precisely, during the course of executing the DO-loop, these values will not be re-computed.
  • step-sizecannot be zero.
  • If the value of step-size is positive (i.e., counting up):
  • The control-var receives the value of initial-value
  • If the value of control-var is less than or equal to the value of final-value, the statements part is executed. Then, the value of step-size is added to the value of control-var. Go back and compare the values of control-var and final-value.
  • If the value of control-var is greater than the value of final-value, the DO-loop completes and the statement following END DO is executed.
  • If the value of step-size is negative (i.e., counting down):
  • The control-var receives the value of initial-value
  • If the value of control-var is greater than or equal to the value of final-value, the statements part is executed. Then, the value of step-size is added to the value of control-var. Go back and compare the values of control-var and final-value.
  • If the value of control-var is less than the value of final-value, the DO-loop completes and the statement following END DO is executed.

Examples

  • In the following, the control-var is Count. It receives -3 before the loop starts. It goes down the loop body and display the values of Count, Count*Count and Count*Count*Count. Thus, -3, 9, -27 are displayed. Then, 2 is added to Count changing its value from -3 to -1. Since this new value of Count (=-1) is less than the final-value, the loop body is executed and displays -1, 1, -1. Then, 2 is added to Count again, changing the value of Count to 1(=(-1)+2). Since this new value is still less than the final-value, the loop body is executed again. This time, it will display 1, 1, 1. Then, 2 is added to Count the third time, changing its value to 3. Since 3 is still less than the final-value, 3, 9, 27 are displayed. After adding 2 to the value of Count the fourth time, the new value of Count is finally greater than the final-value and the DO-loop completes.

INTEGER :: Count

DO Count = -3, 4, 2

WRITE(*,*) Count, Count*Count, Count*Count*Count

END DO

  • In the following, since steps-size is omitted, it is assumed to be 1. Therefore, the control-var Iteration receives 3, 4, and 5 in this order.

INTEGER, PARAMETER :: Init = 3, Final = 5

INTEGER :: Iteration

DO Iteration = Init, Final

WRITE(*,*) 'Iteration ', Iteration

END DO

  • The following uses two Fortran intrinsic functions MIN() and MAX(). It is a count-down loop. The initial-value is the maximum of a, b and c, the final-value is the minimum of a, b and c, and the step-size is -2. Therefore, if the READ statement reads 2, 7, 5 into a, b and , then MAX(a,b,c) and MIN(a,b,c) are 7 and 2, respectively. As a result, control-var List will have values 7, 5, and 3.

INTEGER :: a, b, c

INTEGER :: List

READ(*,*) a, b, c

DO List = MAX(a, b, c), MIN(a, b, c), -2

WRITE(*,*) List

END DO

Frequently Used Loop Tricks

In addition to repeatedly processing some data as shown above, the DO-loop has some other uses as presented in the following examples:

  • Adding numbers: Suppose the value of INTEGER variable Number has been given elsewhere, perhaps with a READ. The following code reads in Number integers and computes their sum into variable Sum.

INTEGER :: Count, Number, Sum, Input

Sum = 0

DO Count = 1, Number

READ(*,*) Input

Sum = Sum + Input

END DO

Sum is initialized to zero. For each iteration, the value of Input, which is read in with READ, is added to the value of Sum.

For example, if the value of Number is 3, and the three input values are 3, 6, and 8 (on different lines), then the final value of Sum is 17 = 3+6+8. Let us look at it closely. Initially, Count receives a value of 1. Since 1 is less than the value of Number (=3), the loop body is executed. The READ statement reads the first input value 3 into Input and this value is added to Sum, changing its value from 0 to 1 (=0+1). Now, END DO is reached and the step-size (=1) is added to Count. Hence, the new value of Count is 2.

Since Count is less than Number, the second input value is read into Input. Now, Input holds 6. Then, 6 is added to the value of Sum, changing its value to 9 (=3+6). The next iteration reads in 8 and adds 8 to Sum. The new value of Sum becomes 17 (=9+8).

A simple modification can compute the average of all input numbers:

INTEGER :: Count, Number, Sum, Input

REAL :: Average

Sum = 0

DO Count = 1, Number

READ(*,*) Input

Sum = Sum + Input

END DO

Average = REAL(Sum) / Number

The above seems obvious. But, please note the use of the function REAL() that converts an INTEGER to a REAL. Without this conversion, Sum /Number is computed as dividing an integer by an integer, yielding an integer result. Consult singe mode arithmetic expressions for details.

  • Factorial: A simple variation could be used to compute the factorial of a positive integer. The factorial of an integer N, written as N!, is defined to be the product of 1, 2, 3, ..., N-1, and N. More precisely, N! = N*(N-1)*(N-2)*...*3*2*1.

INTEGER :: Factorial, N, I

Factorial = 1

DO I = 1, N

Factorial = factorial * I

END DO

In the above, the DO-loop iterates N times. The first iteration multiplies Factorial with 1, the second iteration multiplies Factorial with 2, the third time with 3, ..., the i-th time with I and so on. Therefore, the values that are multiplied with the initial value of Factorial are 1, 2, 3, ..., N. At the end of the DO, the value of Factorial is 1*2*3*...*(N-1)*N.

Some Helpful Notes

There are certain things you should know about DO-loops.

  • The step-size cannot be zero. The following is not a good practice:

INTEGER :: count

DO count = -3, 4, 0

...

END DO

  • Do not change the value of the control-var. The following is not a good practice:

INTEGER :: a, b, c

DO a = b, c, 3

READ(*,*) a ! the value of a is changed

a = b-c ! the value of a is changed

END DO

  • Do not change the value of any variable involved in initial-value, final-value and step-size. The following is not a good practice:

INTEGER :: a, b, c, d, e

DO a = b+c, c*d, (b+c)/e

READ(*,*) b ! initial-value is changed

d = 5 ! final-value is changed

e = -3 ! step-size is changed

END DO

  • When you have a count-down loop, make sure the step-size is negative. If you have a positive step-size, the body of the DO-loop will not be executed. See the way of executing a DO loop above. The body of the following DO will not be executed.

INTEGER :: i

DO i = 10, -10

.....

END DO

  • While you can use REAL type for control-var, initial-value, final-value and step-size, it would be better not to use this feature at all since it may be dropped in future Fortran standard. In the DO-loop below, x successively receives -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75 and 1.0.

REAL :: x

DO x = -1.0, 1.0, 0.25

.....

END DO

You should not use this form of DO-loop in your programs. See the discussion of general DO for the details.

Counting Positive and Negative Input Values

Problem Statement

Given a set of integer input values, write a program to count the number of positive and negative values and compute their sums.

The input is organized as follows:

  • The first line gives the number of data values that follow
  • Starting with the second line, each line contains an integer input value

For example, the following input shows that there are seven input values (i.e., the 7 on the first line), -6, 7, 2, -9, 0, 8 and 0.

7

-6

7

2

-9

0

8

0

Solution

! ------

! This program counts the number of positive and negative

! input values and computes their sums.

! ------

PROGRAM Counting

IMPLICIT NONE

INTEGER :: Positive, Negative

INTEGER :: PosSum, NegSum

INTEGER :: TotalNumber, Count

INTEGER :: Data

Positive = 0 ! # of positive items

Negative = 0 ! # of negative items

PosSum = 0 ! sum of all positive items

NegSum = 0 ! sum of all negative items

READ(*,*) TotalNumber ! read in # of items

DO Count = 1, TotalNumber ! for each iteration

READ(*,*) Data ! read an item

WRITE(*,*) 'Input data ', Count, ': ', Data

IF (Data > 0) THEN ! if it is positive

Positive = Positive + 1 ! count it

PosSum = PosSum + Data ! compute their sum

ELSE IF (Data < 0) THEN ! if it is negative

Negative = Negative + 1 ! count it

NegSum = NegSum + Data ! compute their sum

END IF

END DO

WRITE(*,*) ! display results

WRITE(*,*) 'Counting Report:'

WRITE(*,*) ' Positive items = ', Positive, ' Sum = ', PosSum

WRITE(*,*) ' Negative items = ', Negative, ' Sum = ', NegSum

WRITE(*,*) ' Zero items = ', TotalNumber - Positive - Negative

WRITE(*,*)

WRITE(*,*) 'The total of all input is ', Positive + Negative

END PROGRAM Counting

Click here to download this program.

Program Input and Output

If the data shown above is stored in a file, say data.in and the above program is compiled to an executable count, then executing

count < data.in

will generate the following output:

Input data 1: -6

Input data 2: 7

Input data 3: 2

Input data 4: -9

Input data 5: 0

Input data 6: 8

Input data 7: 0

Counting Report:

Positive items = 3 Sum = 17

Negative items = 2 Sum = -15

Zero items = 2

The total of all input is 5

Discussion

In the program, Positive and Negative are used to count the number of positive and negative data items, and PosSum and NegSum are used to compute their sums. The program first reads the number of input items into TotalNumber and uses it as the final value in a DO-loop.

This loop iterates TotalNumber times. For each iteration, it reads in a new data into Data. The IF-THEN-ELSE-END IF statement tests to see if it is positive or negative, adds 1 into the corresponding counter, and adds the value into the corresponding sum. Note that the number of zero items are not counted, since TotalNumber - Positive - Negative gives the number of zero items. The sum of all zero items are not calculated either, since it must be zero!

Computing Arithmetic, Geometric and Harmonic Means

Problem Statement

The arithmetic mean (i.e., average), geometric mean and harmonic mean of a set of n numbers x1, x2, ..., xn are defined as follows:

Since computing geometric mean requires taking square root, it is further required that all input data values must be positive. As a result, this program must be able to ignore those non-positive items. However, this may cause all input items ignored. Therefore, before computing the means, this program should have one more check to see if there are valid items.

Solution

! ------

! This program reads a series of input data values and

! computes their arithmetic, geometric and harmonic means.

! Since geometric mean requires taking n-th root, all input

! data item must be all positive (a special requirement of

! this program , although it is not absolutely necessary).

! If an input item is not positive, it should be ignored.

! Since some data items may be ignored, this program also

! checks to see if no data items remain!

! ------

PROGRAM ComputingMeans

IMPLICIT NONE

REAL :: X

REAL :: Sum, Product, InverseSum

REAL :: Arithmetic, Geometric, Harmonic

INTEGER :: Count, TotalNumber, TotalValid

Sum = 0.0 ! for the sum

Product = 1.0 ! for the product

InverseSum = 0.0 ! for the sum of 1/x

TotalValid = 0 ! # of valid items

READ(*,*) TotalNumber ! read in # of items

DO Count = 1, TotalNumber ! for each item ...

READ(*,*) X ! read it in

WRITE(*,*) 'Input item ', Count, ' --> ', X

IF (X <= 0.0) THEN ! if it is non-positive

WRITE(*,*) 'Input <= 0. Ignored' ! ignore it

ELSE ! otherwise,

TotalValid = TotalValid + 1 ! count it in

Sum = Sum + X ! compute the sum,

Product = Product * X ! the product

InverseSum = InverseSum + 1.0/X ! and the sum of 1/x

END IF

END DO

IF (TotalValid > 0) THEN ! are there valid items?

Arithmetic = Sum / TotalValid ! yes, compute means

Geometric = Product**(1.0/TotalValid)

Harmonic = TotalValid / InverseSum

WRITE(*,*) 'No. of valid items --> ', TotalValid

WRITE(*,*) 'Arithmetic mean --> ', Arithmetic

WRITE(*,*) 'Geometric mean --> ', Geometric

WRITE(*,*) 'Harmonic mean --> ', Harmonic

ELSE ! no, display a message

WRITE(*,*) 'ERROR: none of the input is positive'

END IF

END PROGRAM ComputingMeans

Click here to download this program.

Program Input and Output

This program uses the same format of input as discussed in previous example. More precisely, the first line gives the number of data items, followed by that number of input line on each which is a data value. Except for the first input value, which gives the number of input, all other values are real numbers.

  • If the input data is
  • 5
  • 1.0
  • 2.0
  • 3.0
  • 4.0
  • 5.0

it will generate the following output. In this input, all data values are positive and none of them is ignored.

Input item 1 --> 1.

Input item 2 --> 2.

Input item 3 --> 3.

Input item 4 --> 4.

Input item 5 --> 5.

No. of valid items --> 5

Arithmetic mean --> 3.

Geometric mean --> 2.6051712

Harmonic mean --> 2.18978071

  • In the following input, the fourth value is negative.
  • 6
  • 1.0
  • 2.0
  • 3.0
  • -4.0
  • 5.0
  • 6.0

The output is shown below:

Input item 1 --> 1.

Input item 2 --> 2.

Input item 3 --> 3.

Input item 4 --> -4.

Input <= 0. Ignored

Input item 5 --> 5.

Input item 6 --> 6.

# of items read --> 6

# of valid items -> 5

Arithmetic mean --> 3.4000001

Geometric mean --> 2.82523465

Harmonic mean --> 2.27272725

  • Now, let us try the following input in which all values are non-positive:
  • 4
  • -1.0
  • -2.0
  • 0.0
  • -3.0

We shall get the following output. The program correctly detects there is no valid data values and displays a message.

Input item 1 --> -1.

Input <= 0. Ignored

Input item 2 --> -2.

Input <= 0. Ignored

Input item 3 --> 0.E+0

Input <= 0. Ignored

Input item 4 --> -3.

Input <= 0. Ignored

ERROR: none of the input is positive

Discussion

This example is quite simple and does not require further explanation.

Computing Factorial

Problem Statement

The factorial of a non-negative integer n, written as n!, is defined as follows:

Write a program that reads in an integer and computes its factorial. This program should detect if the input is negative and display an error message.

Solution

! ------

! Given a non-negative integer N, this program computes

! the factorial of N. The factorial of N, N!, is defined as

! N! = 1 x 2 x 3 x .... x (N-1) x N

! and 0! = 1.

! ------

PROGRAM Factorial

IMPLICIT NONE

INTEGER :: N, i, Answer

WRITE(*,*) 'This program computes the factorial of'

WRITE(*,*) 'a non-negative integer'

WRITE(*,*)

WRITE(*,*) 'What is N in N! --> '

READ(*,*) N

WRITE(*,*)

IF (N < 0) THEN ! input error if N < 0

WRITE(*,*) 'ERROR: N must be non-negative'

WRITE(*,*) 'Your input N = ', N

ELSE IF (N == 0) THEN ! 0! = 1

WRITE(*,*) '0! = 1'

ELSE ! N > 0 here

Answer = 1 ! initially N! = 1

DO i = 1, N ! for each i = 1, 2, ..., N

Answer = Answer * i ! multiply i to Answer

END DO

WRITE(*,*) N, '! = ', Answer

END IF

END PROGRAM Factorial

Click here to download this program.

Program Input and Output

  • If the input is -5, a negative number, the program generates the following output indicating the input is wrong.

This program computes the factorial of

a non-negative integer

What is N in N! -->

-5

ERROR: N must be non-negative

Your input N = -5

  • If the input is a zero, the output is 0! = 1.

This program computes the factorial of

a non-negative integer

What is N in N! -->

0

0! = 1

  • If the input is 5, the factorial of 5 is 5!=1*2*3*4*5=120.

This program computes the factorial of

a non-negative integer

What is N in N! -->

5

5! = 120

  • If the input is 13, the factorial of 15 is 13! = 1*2*3*...*13=1932053504

This program computes the factorial of

a non-negative integer

What is N in N! -->

13

13! = 1932053504

Discussion

The basics of writing a factorial computation program has been discussed in a factorial example of countingDO.

It is worthwhile to note that most CPU's do not report integer overflow. As a result, on a typical computer today, the maximum factorial is around 13!. If you try this program on a PC, you should get 13! = 1932053504 and 14! = 1278945280. But, 13! > 14! is obviously incorrect. Then, we have 15! = 2004310016, 16! = 2004189184, and 17! = -288522240. These results are obviously wrong. This shows that a typical PC can only handle up to 13!