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!