# Fortran 90 Tutorial_3 by stariya

VIEWS: 11 PAGES: 51

• pg 1
```									REPETITIVE EXECUTION

SELECT THE TOPICS YOU WISH TO REVIEW:
Repetitive Execution

Counting DO-Loop      Programming Examples:

Counting Positive and Negative Input Values

Computing Arithmetic, Geometric and Harmonic Means

Computing Factorial

General DO-Loop with EXIT      Programming 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-Loop      Programming 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)

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

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-size cannot be zero.
   If the value of step-size is positive (i.e., counting up):
1. The control-var receives the value of initial-value
2. 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.
3.   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):
1. The control-var receives the value of initial-value
2. 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.
3. 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

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
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
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.

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

DO Count = 1, TotalNumber       ! for each iteration
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

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

DO Count = 1, TotalNumber              ! for each item ...
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

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

WRITE(*,*)        'This program computes the factorial of'
WRITE(*,*)        'a non-negative integer'
WRITE(*,*)
WRITE(*,*)        'What is N in 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
END DO
WRITE(*,*) N, '! = ', Answer
END IF

END PROGRAM Factorial

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

   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 counting DO.

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!

GENERAL DO-LOOP WITH EXIT

The general DO-loop is actually very simple. But, to use it properly, you need to be very careful,
since it may never stop. The general DO-loop has a form as follows:

DO
statements
END DO
Between DO and END DO, there are statements. These statements are executed over and over without any chance
to get out of the DO-loop. Here is an example,

REAL :: x, y, z
DO
y = x*x
z = x*x*x
WRITE(*,*) x, ' square = ', y, ' cube = ', z
END DO
One iteration of this loop consists of reading a value for x, computing its square and cube to y and z, respectively,
and displaying the results. Then, the execution goes back to the top and executes the four statements again.
Consequently, this loop is executed over and over and has no chance to stop at all. A loop that never stops is
usually referred to as an infinite loop. To stop the iteration of a DO-loop, we need something else.
THE EXIT STATEMENT
The EXIT is as simple as writing down the word EXIT. It is used to bail out the containing loop.

DO
statements-1
EXIT
statements-2
END DO
In the above, statements-1 is executed followed by the EXIT statement. Once the EXIT statement is reached, the
control leaves the inner-most DO-loop that contains the EXIT statement. Therefore, in the above case, statements-
2 will never be executed.

Since it must be some reason for bailing out a DO-loop, the EXIT statement is usually used with
an IF or even an IF-THEN-ELSE-END IF statement in one of the following forms. Note that
these are not the only cases in which you can use EXIT.

DO
statements-1
IF (logical-expression)                EXIT
statements-2
END DO

DO
statements-1
IF (logical-expression) THEN
statements-THEN
EXIT
END IF
statements-2
END DO
For each iteration, statements in statements-1 are executed, followed the evaluation of the logical-expression. If
the result is .FALSE., statements in statements-2 are executed. This completes one iteration and the control goes
back to the top and executes statements-1 again for next iteration.

If the result of evaluating logical-expression is .TRUE., the first form will executes EXIT,
which immediately stops the execution of the DO-loop. The next statement to be executed is the
one following END DO.

For the second form, if the result of evaluating logical-expression is .TRUE., statements in
statements-THEN are executed followed by the EXIT statement, which brings the execution
to the statement following END DO. Therefore, statements in statements-THEN will do
some "house-keeping" work before leaving the DO-loop. If there is no "house-keeping"
work, the first form will suffice.

EXAMPLES
   The following code reads in values into variable x until the input value becomes negative. All input
values are added to Sum. Note that the negative one is not added to Sum, since once the code sees
such a negative value, EXIT is executed.

INTEGER :: x, Sum

Sum = 0
DO
IF (x < 0) EXIT
Sum = Sum + x
END DO

   The following is an example that "simulates" a counting DO-loop using REAL variables. Variable x is
initialized to the initial value Lower and serves as a control variable. Before any statement of the DO-
loop is executed, the value of x is checked to see if it is greater than the final value Upper. If it is, EXIT is
executed, leaving the loop. Otherwise, the loop body is executed and before goes back to the top, the
control variable x must be increased by the step size Step. This loop will display -1.0, -0.75, -0.5, -0.25,
0.0, 0.25, 0.5, 0.75 and 1.0, each of them is on a separate line.

REAL, PARAMETER :: Lower = -1.0, Upper = 1.0, Step = 0.25
REAL            :: x

x = Lower ! initialize the control variable (DON'T FORGET)
DO
IF (x > Upper) EXIT   ! is it > final-value?
WRITE(*,*) x          ! no, do the loop body
x = x + Step          ! an increase by step-size
END DO

   In many cases, your program may expect an input satisfying certain conditions. DO-loop can help a lot.
The following code keeps asking and checking if the input integer value is in the range of 0 and 10
inclusive. If it is not, the program warns the user and reads again until the input is in the stated range.

INTEGER :: Input

DO
WRITE(*,*) 'Type an integer in the range of 0 and 10 please --> '
IF (0 <= Input .AND. Input <= 10) EXIT
WRITE(*,*) 'Your input is out of range. Try again'
END DO

   One of the most commonly seen problem is forgetting to change the logical-expression that may cause
an EXIT. The following DO-loop never stops and keeps displaying 5, 5, 5, 5, ..., forever. The reason? The
value of i is never changed.

INTEGER       :: i

i = 5
DO
IF (i < -2) EXIT
WRITE(*,*) i
END DO

The following is another example:

INTEGER :: i = 1, j = 5

DO
IF (j < 0)         EXIT
WRITE(*,*)         i
i = i + 1
END DO

   Sometimes we just forget to initialize the control-var . We really do not know what would be displayed
since the value of i is unknown at the beginning of the DO and is certainly unknown after executing i = i
- 1.

INTEGER :: i

DO
IF (i <= 3) EXIT
WRITE(*,*) i
i = i - 1
END DO

DETERMINING THE MINIMUM AND MAXIMUM OF INPUT DATA

PROBLEM STATEMENT

Suppose we have a set of non-negative input integers terminated with a negative value. These
input values are on separate lines. Write a program to determine the number of input data items,
excluding the negative one at the end, and compute the minimum and the maximum. For
example, the following input contains 7 data values with the seventh being negative. Of the six
non-negative ones, the minimum and maximum are 2 and 9, respectively.

5
3
9
2
7
4
-1

SOLUTION
! ------------------------------------------------------
! This program reads in a number of integer input until
! a negative one, and determines the minimum and maximum
! of the input data values.
! ------------------------------------------------------

PROGRAM MinMax
IMPLICIT NONE

COMPUTING THE SQUARE ROOT OF A POSITIVE NUMBER

PROBLEM STATEMENT

The square root of a positive number b can be computed with Newton's formula:

where x above starts with a "reasonable" guess. In fact, you can always start with b or some
other value, say 1.

With b and a guess value x, a new guess value is computed with the above formula. This process
continues until the new guess value and the current guess value are very close. In this case, either
one can be considered as an approximation of the square root of b.

Write a program that reads in a REAL value and a tolerance, and computes the square root until
the absolute error of two adjacent guess values is less than the tolerance value.

SOLUTION
!   ---------------------------------------------------------
!   This program uses Newton's method to find the square
!   root of a positive number. This is an iterative method
!   and the program keeps generating better approximation
!   of the square root until two successive approximations
!   have a distance less than the specified tolerance.
!   ---------------------------------------------------------

PROGRAM SquareRoot
IMPLICIT NONE

REAL    :: Input, X, NewX, Tolerance
INTEGER :: Count

Count = 0                                      ! count starts with 0
X     = Input                                  ! X starts with the input value
DO                                             ! for each iteration
Count = Count + 1                                   !        increase the iteration count
NewX = 0.5*(X + Input/X)                            !        compute a new approximation
IF (ABS(X - NewX) < Tolerance)                    EXIT       ! if they are very close, exit
X = NewX                                            !        otherwise, keep the new one
END DO

WRITE(*,*)        'After ', Count, ' iterations:'
WRITE(*,*)        ' The estimated square root is ', NewX
WRITE(*,*)        ' The square root from SQRT() is ', SQRT(Input)
WRITE(*,*)        ' Absolute error = ', ABS(SQRT(Input) - NewX)

END PROGRAM SquareRoot

PROGRAM INPUT AND OUTPUT
If the input are 10.0 for b and 0.00001 for the tolerance, the following output shows that it requires 6 iterations to
reach an approximation of square root of 10. Comparing the result with the one obtained from Fortran intrinsic
function SQRT(), the absolute error is zero.

After 6 iterations:
The estimated square root is 3.1622777
The square root from SQRT() is 3.1622777
Absolute error = 0.E+0

If the input are 0.5 for b and 0.00001 for the tolerance, it takes 4 iterations to reach an
approximation of the square root of 0.5. The value from using Fortran intrinsic function SQRT()
is 0.707106769 and again the absolute error is 0.

After 4 iterations:
The estimated square root is 0.707106769
The square root from SQRT() is 0.707106769
Absolute error = 0.E+0

DISCUSSION

    This program uses X to hold the input value for b and uses NewX to hold the new guess value. The initial
guess is the input value.
    From the current guess, using Newton's formula, the new guess is compared as
      NewX = 0.5*(X + Input/X)
    Then, the absolute error of X and NewX is computed. If it is less than the tolerance value, EXIT the loop
and display the results. Otherwise, the current guess is replaced with the new guess and go back for the
next iteration.

COMPUTING EXP(X)
PROBLEM STATEMENT

The exponential function, EXP(x), is defined to be the sum of the following infinite series:

Write a program that reads in a REAL value and computes EXP() of that value using the series
until the absolute value of a term is less than a tolerance value, say 0.00001.

SOLUTION
!   ---------------------------------------------------------
!   This program computes exp(x) for an input x using the
!   infinite series of exp(x). This program adds the
!   terms together until a term is less than a specified
!   tolerance value. Thus, two values are required:
!   the value for x and a tolerance value. In this program,
!   he tolerance value is set to 0.00001 using PARAMETER.
!   ---------------------------------------------------------

PROGRAM Exponential
IMPLICIT NONE

INTEGER               ::   Count             !   # of terms used
REAL                  ::   Term              !   a term
REAL                  ::   Sum               !   the sum of series
REAL                  ::   X                 !   the input x
REAL, PARAMETER       ::   Tolerance = 0.00001      ! tolerance

Count = 1                                    !   the first term is 1 and counted
Sum     = 1.0                                !   thus, the sum starts with 1
Term = X                                     !   the second term is x
DO                                           !   for each term
IF (ABS(Term) < Tolerance)        EXIT   !      if too small, exit
Sum    = Sum + Term                      !      otherwise, add to sum
Count = Count + 1                        !      count indicates the next term
Term = Term * (X / Count)                !      compute the value of next term
END DO

WRITE(*,*)      'After ', Count, ' iterations:'
WRITE(*,*)      ' Exp(', X, ') = ', Sum
WRITE(*,*)      ' From EXP()    = ', EXP(X)
WRITE(*,*)      ' Abs(Error)    = ', ABS(Sum - EXP(X))

END PROGRAM Exponential
PROGRAM INPUT AND OUTPUT
If the input value is 10.0, the following output shows that it requires 35 iterations to reach EXP(10.0)=22026.4648.
Comparing the result with the one obtained from Fortran intrinsic function EXP(), the absolute error is zero.

After 35 iterations:
Exp(10.) = 22026.4648
From EXP()   = 22026.4648
Abs(Error)   = 0.E+0

If the input is -5.0, it takes 21 iterations to reach EXP(-5.0)=6.744734943E-3. The value from
using Fortran intrinsic function is 6.737946998E-3 and the absolute error is 6.787944585E-6.

After 21 iterations:
Exp(-5.) = 6.744734943E-3
From EXP()   = 6.737946998E-3
Abs(Error)   = 6.787944585E-6

DISCUSSION


i
One obvious way of writing this program is computing each term directly using the formula x /i!.
i
However, this is not a wise way, since both x and i! could get very large when x or i is large. One way to
overcome this problem is rewriting the term as follows:

Therefore, the (i+1)-th term is equal to the product of the i-th term and x/(i+1). In the
program, variable Term is used to save the value of the current term and is updated with

Term = Term * (X / Count)

where Count is the value of i+1.

   Variable Sum is used to accumulate the values of terms.
   Since the tolerance value is usually small, the first term whose value is 1 cannot be less than the tolerance
value. Therefore, the computation starts with the second term and 1 is saved to Sum.
   Count indicates which term is under consideration. Its plays the role of i in the infinite series shown
above.
   Since the computation starts with the first term, the value of the first term, x, is saved to Term.
   For each iteration, the absolute value of Term is checked to see if it is less than the tolerance value
Tolerance. If it is, the computation is done and EXIT.
   Otherwise, this term is added to Sum and prepare for the next term. Before this, Count is increased by
one to point to the next term and consequently the next term is computed as Term * (X / Count).

COMPUTING THE GREATEST COMMON DIVISOR OF TWO POSITIVE INTEGERS
PROBLEM STATEMENT

The Greatest Common Divisor, GCD for short, of two positive integers can be computed with
Euclid's division algorithm. Let the given numbers be a and b, a >= b. Euclid's division
algorithm has the following steps:

1.   Compute the remainder c of dividing a by b.
2.   If the remainder c is zero, b is the greatest common divisor.
3.   If c is not zero, replace a with b and b with the remainder c. Go back to step (1).

Write a program that reads in two integers and computes their greatest common divisor. Note that these two
input could be in any order.

SOLUTION
!   ---------------------------------------------------------
!   This program computes the GCD of two positive integers
!   using the Euclid method. Given a and b, a >= b, the
!   Euclid method goes as follows: (1) dividing a by b yields
!   a reminder c; (2) if c is zero, b is the GCD; (3) if c is
!   no zero, b becomes a and c becomes c and go back to
!   Step (1). This process will continue until c is zero.
!   ---------------------------------------------------------

PROGRAM GreatestCommonDivisor
IMPLICIT NONE

INTEGER        :: a, b, c

WRITE(*,*) 'Two positive integers please --> '
IF (a < b) THEN       ! since a >= b must be true, they
c = a              ! are swapped if a < b
a = b
b = c
END IF

DO                                ! now we have a <= b
c = MOD(a, b)                  !    compute c, the reminder
IF (c == 0) EXIT               !    if c is zero, we are done.                    GCD = b
a = b                          !    otherwise, b becomes a
b = c                          !    and c becomes b
END DO                            !    go back

WRITE(*,*) 'The GCD is ', b

END PROGRAM GreatestCommonDivisor

PROGRAM INPUT AND OUTPUT
   If the input values are 46332 and 71162, the computed GCD is 26.

46332 71162

The GCD is 26

   If the input values are 128 and 32, the GCD is 32.

128 32

The GCD is 32

   If the input values are 100 and 101, the GCD is 1 and 100 and 101 are relatively prime.

100 101

The GCD is 1

   If the input values are 97 and 97, the GCD is of course 97.
       Two positive integers please -->
97 97

The GCD is 97

DISCUSSION

   Since there is no specific order for the two input values, it is possible that a may be less than b. In this
case, these two values must be swapped.
   Thus, before entering the DO-loop, we are sure that a >= b holds.
   Then, the remainder is computed and stored to c. If c is zero, the program EXITs and displays the value of
b as the GCD. The remainder is computed using Fortran intrinsic function MOD().
   If c is not zero, b becomes a and c becomes b, and reiterates.
   If we need to display the result as follows:
      The GCD of 46332 and 71162 is 26

would the following change to the WRITE statement work?

WRITE(*,*) 'The GCD of ', a, ' and ', b, ' is ', b

CHECKING IF A POSITIVE INTEGER IS A PRIME NUMBER

PROBLEM STATEMENT
An positive integer greater than or equal to 2 is a prime number if the only divisor of this integer
is 1 and itself.

Write a program that reads in an arbitrary integer and determines if it is a prime number.

SOLUTION
!   --------------------------------------------------------------------
!   Given an integer, this program determines if it is a prime number.
!   This program first makes sure the input is 2. In this case, it is
!   a prime number. Then, it checks to see the input is an even
!   number. If the input is odd, then this program divides the input
!   with 3, 5, 7, ....., until one of two conditions is met:
!      (1) if one these odd number evenly divides the input, the
!           input is not a prime number;
!      (2) if the divisor is greater than the square toot of the
!           input, the input is a prime.
!   --------------------------------------------------------------------

PROGRAM Prime
IMPLICIT NONE

INTEGER      :: Number                                   ! the input number
INTEGER      :: Divisor                                  ! the running divisor

IF (Number < 2) THEN                  ! not a prime if < 2
WRITE(*,*) 'Illegal input'
ELSE IF (Number == 2) THEN            ! is a prime if = 2
WRITE(*,*) Number, ' is a prime'
ELSE IF (MOD(Number,2) == 0) THEN     ! not a prime if even
WRITE(*,*) Number, ' is NOT a prime'
ELSE                                  ! we have an odd number here
Divisor = 3                        ! divisor starts with 3
DO                                 ! divide the input number
IF (Divisor*Divisor > Number .OR. MOD(Number, Divisor) == 0)                     EXIT
Divisor = Divisor + 2          ! increase to next odd
END DO
IF (Divisor*Divisor > Number) THEN       ! which condition fails?
WRITE(*,*) Number, ' is a prime'
ELSE
WRITE(*,*) Number, ' is NOT a prime'
END IF
END IF
END PROGRAM Prime

PROGRAM INPUT AND OUTPUT

   If the input value is -1, the output is a message saying the input is not legal.

Illegal input
   If the input is 2, it is a prime number.

2 is a prime

   If the input is 3, it is also a prime number.

3 is a prime

   If the input is 46, it is not a prime number since it is divisible by 2.

46 is NOT a prime

   If the input is 97, it is a prime number.

97 is a prime

   If the input is 9797, it is not a prime since it is divisible by 97.

9797 is NOT a prime

DISCUSSION

   Since the input is an arbitrary integer, the program first makes sure its value is greater than or equal to 2;
otherwise, a message is displayed.
   If the input is greater than or equal to 2, the program checks if it is actually equal to 2. If it is, just reports
"2 is a prime".
   The next step is screening out all even numbers. Note that 2 has been checked before the control gets to
the second ELSE-IF. If the input is divisible by 2, it is not a prime number.
   If the control can reach here, the input is an odd number greater than or equal to 3. Then, the program
uses 3, 5, 7, 9, 11, ... these odd numbers as divisors to divide the input value stored in Number. These
divisors are successively stored in Divisor.
   Of course, these divisors should start with 3; but, the question is when to stop. A naive answer would be
"let us try up to Number-1" This is too slow since Number cannot be evenly divided by Number-1.

A better choice is the square root of Number? Why is this strange value? If Number is
divisible by a, then we can write Number=a*b for some b. If a is less than or equal to b,
then a must be smaller than or equal to the square root of Number.

Therefore, the upper limit of Divisor is the square root of Number. Stated in a slightly
different way, it is "the square of Divisor is less than or equal to Number". This is better
since it only uses integer arithmetic, while the one using square root involves REAL
numbers.

   In the DO-loop, the value for Divisor starts with 3. As long as the square of Divisor is less than or equal to
Number and Number is not divisible by Divisor, the iteration continues.

Since Divisor can only be odd numbers, step-size is 2.
This loop continues until one of the two conditions holds. If Divisor*Divisor > Number
holds, then all odd numbers that are greater than or equal to 3 and less than or equal to the
square root of Number have been tried and none of them can evenly divide Number.
Therefore, Number is a prime number.

If MOD(Number,Divisor) == 0 holds, Divisor divides Number and Number is not a
prime.

   Let us take a look at a few examples:
1. Let Number be 3. Divisor starts with 3. Since condition Divisor*Divisor > Number holds
immediately, 3 is a prime number.
2. Let Number be 5. Divisor starts with 3. Since condition Divisor*Divisor > Number holds
immediately, 5 is a prime number.
3. Let Number be 11. Divisor starts with 3. In the first iteration, both Divisor*Divisor > Number and
MOD(Number,Divisor) == 0 fail. So, Divisor is increased by 2, becoming 5. In the second
iteration, Divisor*Divisor > Number holds and 11 is a prime.
4. Let Number be 91. Divisor starts with 3. In the first iteration, both Divisor*Divisor > Number and
MOD(Number,Divisor) == 0 fail. So, Divisor is increased by 2, becoming 5. In the second
iteration, both conditions still fail and Divisor is increased to 7. In the third iteration,
MOD(Number,Divisor) == 0 holds and 91 is not a prime.

NESTED DO-LOOPS

Just like an IF-THEN-ELSE-END IF can contain another IF-THEN-ELSE-END IF (see
nested IF for the details), a DO-loop can contain other DO-loops in its body. The body of the
contained DO-loop, usually referred to as the nested DO-loop, must be completely inside the
containing DO-loop. Note further that an EXIT statement only brings the control out of the
inner-most DO-loop that contains the EXIT statement.

Suppose we have the following nested DO loops:

DO
statements-1
DO
statement-2
END DO
statement-3
END DO
Each iteration of the outer DO starts with statements-1. When the control reaches the inner DO, statements-2 is
executed until some condition of the inner DO brings the control out of it. Then, statements-3 is executed and this
completes one iteration. Any EXIT in the inner DO brings the control out of the inner DO to the first statement in
statement-3.

The following are a few simple examples:
   In the following nested loops, the outer one has i running from 1 to 9 with step size 1. For each iteration,
say the i-th one, the inner loop iterates 9 times with values of j being 1, 2, 3, 4, 5, 6, 7, 8, 9. Therefore,
with i fixed, the WRITE is executed 9 times and the output consists of i*1, i*2, i*3, ..., i*9.

INTEGER :: i, j

DO i = 1, 9
DO j = 1, 9
WRITE(*,*)           i*j
END DO
END DO

Once this is done, the value of i is advanced to the next one, and the inner loop will iterate 9 times
again displaying the product of the new i and 1, 2, 3,4 ..., 9.

The net effect is a multiplication table. For i=1, the value if 1*1, 1*2, 1*3, ..., 1*9 are
displayed; for i=2, the displayed values are 2*1, 2*2, 2*3, ..., 2*9; ...; for i=9, the
displayed values are 9*1, 9*2, 9*3, ..., 9*9.

   The following shows a nested DO-loop. The outer one lets u run from 2 to 5. For each u, the inner DO
lets v runs from 1 to u-1. Therefore, when u is 2, the values for v is from 1 to 1. When u is 3, the values
for v are 1 and 2. When u is 4, the values for v are 1, 2, and 3. Finally, when u is 5, the values for v are 1,
2, 3 and 4.

INTEGER :: u, v
INTEGER :: a, b, c

DO u = 2, 5
DO v = 1, u-1
a = 2*u*v
b = u*u - v*v
c = u*u + v*v
WRITE(*,*) a, b, c
END DO
END DO

The above discussion can be summarized in the following table:

u Values for v

2 1

3 1 2

4 1 2 3

5 1 2 3 4
For each pair of u and v, the inner loop computes a, b and c. Thus, it will generate
the following result (please verify it):

u v a b c

2 1 4 3 5

1 6 8 10
3
2 12 5 13

1 8 15 17

4 2 16 12 20

3 24 7 25

1 10 24 26

2 20 21 29
5
3 30 16 34

4 40 9 41

   It is obvious that the inner DO-loop computes the sum of all integers in the range of 1 and i (i.e., Sum is
equal to 1+2+3+...+i). Since i runs from 1 to 10, the following loop computes ten sums: 1, 1+2, 1+2+3,
1+2+3+4, ...., 1+2+3+...+9, and 1+2+3+...+9+10.

INTEGER :: i, j, Sum

DO i = 1, 10
Sum = 0
DO j = 1, i
Sum = Sum + j
END DO
WRITE(*,*) Sum
END DO

   The program below uses Newton's method for computing the square root of a positive number. In fact,
it computes the square roots of the numbers 0.1, 0.1, ..., 0.9 and 1.0.

REAL :: Start = 0.1, End = 1.0, Step = 0.1
REAL :: X, NewX, Value

Value = Start
DO
IF (Value > End) EXIT
X = Value
DO
NewX = 0.5*(X + Value/X)
IF (ABS(X - NewX) < 0.00001) EXIT
X = NewX
EBD DO
WRITE(*,*) 'The square root of ', Value, ' is ', NewX
Value = Value + Step
END DO

Newton's method is taken directly from the programming example, where X is the current guess, NewX
is the new guess, and Value is the number for square root computation. The EXIT statement brings the
execution of the inner DO to the WRITE statement.

If the inner loop is removed, we have the outer loop as follows:

REAL :: Start = 0.1, End = 1.0, Step = 0.1
REAL :: X, NewX, Value

Value = Start
DO
IF (Value > End) EXIT
!
! the inner loop computes the result in NewX
!
WRITE(*,*) 'The square root of ', Value, ' is ', NewX
Value = Value + Step
END DO

It is clear that the value of Value starts with 0.1 and have a step size 0.1 until 1.0. Thus, the values of
Value are 0.1, 0.2, 0.3, ..., 0.9 and 1.0. For each value of Value, the inner loop computes the square root
of Value. The EXIT statement in the outer loop brings the control out of the outer loop.

COMPUTING CLASSES AVERAGES

PROBLEM STATEMENT

There are four sessions of CS110 and CS201, each of which has a different number of students.
Suppose all students take three exams. Someone has prepared a file that records the exam scores
of all students. This file has a form as follows:

4
3
97.0    87.0    90.0
100.0   78.0    89.0
65.0    70.0    76.0
2
100.0   100.0 98.0
97.0    85.0 80.0
4
78.0 75.0 90.0
89.0 85.0 90.0
100.0 97.0 98.0
56.0 76.0 65.0
3
60.0 65.0 50.0
100.0 99.0 96.0
87.0 74.0 81.0
The first number 4 gives the number of classes in this file. For each class, it starts with an integer, giving the
number of students in that class. Thus, the first class has 3 students, the second has 2, the third has 4 and the
fourth has 3. Following the number of students, there are that number of lines each of which contains the three
scores of a student.

Write a program that reads in a file of this form and computes the following information:

1.   the average of each student;
2.   the class average of each exam; and
3.   the grant average of the class.

SOLUTION
!   ----------------------------------------------------------
!   This program computes the average of each student and the
!   the average of the class. The input file starts with an
!   integer giving the number of classes. For each class, the
!   input starts with an integer giving the number of students
!   of that class, followed that number of lines on each of
!   which there are three scores. This program reads in the
!   scores and computes their average and also the class
!   averages of each score and the grant average of the class.
!   ----------------------------------------------------------

PROGRAM ClassAverage
IMPLICIT NONE

INTEGER     ::   NoClass              ! the no. of classes
INTEGER     ::   NoStudent            ! the no. of students in each class
INTEGER     ::   Class, Student       ! DO control variables
REAL        ::   Score1, Score2, Score3, Average
REAL        ::   Average1, Average2, Average3, GrantAverage

DO Class = 1, NoClass           ! for each class, do the following
READ(*,*) NoStudent          !   the # of student in this class
WRITE(*,*)
WRITE(*,*) 'Class ', Class, ' has ', NoStudent, ' students'
WRITE(*,*)
Average1 = 0.0               !   initialize average variables
Average2 = 0.0
Average3 = 0.0
DO Student = 1, NoStudent    !   for each student in this class
Average1 = Average1 + Score1       ! prepare for class average
Average2 = Average2 + Score2
Average3 = Average3 + Score3
Average = (Score1 + Score2 + Score3) / 3.0   ! average of this one
WRITE(*,*) Student, Score1, Score2, Score3, Average
END DO
WRITE(*,*) '----------------------'
Average1      = Average1 / NoStudent   ! class average of score1
Average2      = Average2 / NoStudent   ! class average of score2
Average3      = Average3 / NoStudent   ! class average of score3
GrantAverage = (Average1 + Average2 + Average3) / 3.0
WRITE(*,*) 'Class Average: ', Average1, Average2, Average3
WRITE(*,*) 'Grant Average: ', GrantAverage
END DO

END PROGRAM ClassAverage

PROGRAM INPUT AND OUTPUT
The input shown above should produce the following output:

Class 1 has 3 students

1, 97., 87., 90., 91.3333359
2, 100., 78., 89., 89.
3, 65., 70., 76., 70.3333359
----------------------
Class Average: 87.3333359, 78.3333359,                   85.
Grant Average: 83.5555573

Class 2 has 2 students

1, 100., 100., 98., 99.3333359
2, 97., 85., 80., 87.3333359
----------------------
Class Average: 98.5, 92.5, 89.
Grant Average: 93.3333359

Class 3 has 4 students

1, 78., 75., 90., 81.
2, 89., 85., 90., 88.
3, 100., 97., 98., 98.3333359
4, 56., 76., 65., 65.6666641
----------------------
Class Average: 80.75, 83.25, 85.75
Grant Average: 83.25

Class 4 has 3 students

1, 60., 65., 50., 58.3333321
2, 100., 99., 96., 98.3333359
3, 87., 74., 81., 80.6666641
----------------------
Class Average: 82.3333359,                 79.3333359,         75.6666641
Grant Average: 79.1111145

DISCUSSION
This is a relatively easy problem. Here is an analysis in case you need it.

Since for each class we need to compute the average of each student, the class average of each
exam, and the grant average of the whole class, we might immediately come up the following
scheme:

DO Class = 1, NoClass
compute various average for this class
display exam averages and class the grant average
END DO
Thus, "compute various average for the class" becomes the job of the inner loop. This loop should read in the
scores of each student and do some computation as follows:

DO Student = 1, NoStudent
compute the average of this student
compute the exam averages
END DO
Now, the only trouble is how to compute the exam averages. In fact, this inner loop has no way to compute the
exam averages directly; but, it could compute the sum of the scores of a particular exam. After this inner loop
ends, the outer loop could divide the sum with the number of students to obtain the average. To accumulate these
sums, we need to initialize variables. Thus, the result is:

Average1 = 0.0
Average2 = 0.0
Average3 = 0.0
DO Student = 1, NoStudent
Average1 = Average1 + Score1
Average2 = Average2 + Score2
Average3 = Average3 + Score3
Average = (Score1 + Score2 + Score3) / 3.0
WRITE(*,*) Student, Score1, Score2, Score3, Average
END DO
WRITE(*,*) '----------------------'
Average1           = Average1 / NoStudent
Average2           = Average2 / NoStudent
Average3           = Average3 / NoStudent
GrantAverage = (Average1 + Average2 + Average3) / 3.0
In the above, Average1, Average2 and Average3 are for the exam averages. They must be initialized right before
entering the inner DO-loop, since the exam averages are computed for each class. The actual average is computed
right after the inner DO-loop by dividing Average1, Average2 and Average3 with the number of students
NoStudents. Once we have the exam averages, the grant average is computed as the average of these exam
averages.
COMPUTING A SET OF VALUES OF EXP(X)

PROBLEM STATEMENT

In a previous example we have discussed the way of using infinite series for computing the
exponential function EXP(x). The exponential function, EXP(x), is usually defined to be the
sum of the following infinite series:

Write a program that reads in an initial value Begin, a final value End and a step size Step, and
computes the exponential function value at Begin, Begin+Step, Begin+2*Step, ...

SOLUTION
!   --------------------------------------------------------------
!   This program computes exp(x) for a range of x. The range
!   is in the form of beginning value, final value and step size.
!   For each value in this range, the infinite series of exp(x)
!   is used to compute exp(x) up to a tolerance of 0.00001.
!   This program display the value of x, the exp(x) from infinite
!   series, the exp(x) from Fortran's intrinsic function exp(x),
!   the absolute error, and the relative error.
!   --------------------------------------------------------------

PROGRAM Exponential
IMPLICIT NONE

INTEGER            ::   Count             !      term count
REAL               ::   Term              !      a term
REAL               ::   Sum               !      the sum of series
REAL               ::   X                 !      running value
REAL               ::   ExpX              !      EXP(X)
REAL               ::   Begin, End, Step !       control values
REAL, PARAMETER    ::   Tolerance = 0.00001         ! tolerance

WRITE(*,*)    'Initial, Final and Step please --> '

X = Begin                                    ! X starts with the beginning value
DO
IF (X >    End) EXIT                      !   if X is > the final value, EXIT
Count =    1                              !   the first term is 1 and counted
Sum    =   1.0                            !   thus, the sum starts with 1
Term =     X                              !   the second term is x
ExpX =     EXP(X)                         !   the exp(x) from Fortran's EXP()
DO                                        !   for each term
IF (ABS(Term) < Tolerance)                  EXIT ! if too small, exit
Sum   = Sum + Term                             !   otherwise, add to sum
Count = Count + 1                              !   count indicates the next term
Term = Term * (X / Count)                      !   compute the value of next term
END DO

WRITE(*,*)        X, Sum, ExpX, ABS(Sum-ExpX), ABS((Sum-ExpX)/ExpX)

X = X + Step
END DO

END PROGRAM Exponential

PROGRAM INPUT AND OUTPUT
If the input for Begin, End and Step are -1.0, 1.0 and 0.1, the program would generate the following output.

Initial, Final and Step please -->
-1., 0.367881894, 0.36787945, 2.443790436E-6, 6.642911103E-6
-0.899999976, 0.406570643, 0.40656966, 9.834766388E-7, 2.41896214E-6
-0.799999952, 0.449325144, 0.449328989, 3.844499588E-6, 8.556090506E-6
-0.699999928, 0.496584028, 0.496585339, 1.311302185E-6, 2.640638058E-6
-0.599999905, 0.5488168, 0.548811674, 5.125999451E-6, 9.340179531E-6
-0.499999911, 0.606532216, 0.606530726, 1.490116119E-6, 2.456785978E-6
-0.399999917, 0.670314729, 0.670320094, 5.36441803E-6, 8.002770301E-6
-0.299999923, 0.740817249, 0.740818262, 1.013278961E-6, 1.367783398E-6
-0.199999928, 0.818733335, 0.818730831, 2.503395081E-6, 3.05765343E-6
-9.999992698E-2, 0.904833436, 0.904837489, 4.053115845E-6, 4.479385552E-
6
7.450580597E-8, 1., 1.00000012, 1.192092896E-7, 1.192092753E-7
0.100000076, 1.10516667, 1.10517097, 4.291534424E-6, 3.883140835E-6
0.200000077, 1.22140002, 1.22140288, 2.861022949E-6, 2.342407242E-6
0.300000072, 1.34985793, 1.34985888, 9.536743164E-7, 7.064992928E-7
0.400000066, 1.4918189, 1.49182475, 5.841255188E-6, 3.915510206E-6
0.50000006, 1.64871967, 1.64872134, 1.668930054E-6, 1.012257258E-6
0.600000083, 1.82211316, 1.822119, 5.841255188E-6, 3.205748499E-6
0.700000107, 2.01375127, 2.01375294, 1.668930054E-6, 8.287660194E-7
0.800000131, 2.22553682, 2.22554111, 4.291534424E-6, 1.928310667E-6
0.900000155, 2.45960236, 2.45960355, 1.192092896E-6, 4.846687034E-7
The first column shows the data values (i.e., -1.0, -0.9, ..., 1.0), the second is the values from using infinite series
with a tolerance value 0.00001, the third column contains the values from Fortran's intrinsic function EXP(), the
forth column has the absolute errors, and the fifth column has the relative errors.

Let S be the sum computed using infinite series and exp(x) be the result from Fortran's intrinsic
function. Then, the absolute error and relative error are defined as follows:
You may find out that the value for X are not -1.0, -0.9, -0.8, ..., 0.0, 0.1, 0.2, ..., 0.9 and 1.0. It
contains errors. For example, the last value should be 1.0 instead of 0.900000155. This is a
problem of precision being not high enough. See the KIND attribute in a later chapter.

DISCUSSION

   For the computation using infinite series, see a previous example for the details.
   Since the data points are Begin, Begin+Step, Begin+2*Step and so on, it is simply a DO-loop as follows:

X = Begin
DO
IF (X > End) EXIT
... compute EXP(X) here ...
X = X + Step
END DO

   Inserting the computation part into the place "... computing EXP(X) here ..." gives the program shown
above.

ARMSTRONG NUMBERS

PROBLEM STATEMENT

An Armstrong number of three digits is an integer such that the sum of the cubes of its digits is
equal to the number itself. For example, 371 is an Armstrong number since 3**3 + 7**3 + 1**3
= 371.

Write a program to find all Armstrong number in the range of 0 and 999.

SOLUTION
!   ---------------------------------------------------------------
!   This program computes all Armstrong numbers in the range of
!   0 and 999. An Armstrong number is a number such that the sum
!   of its digits raised to the third power is equal to the number
!   itself. For example, 371 is an Armstrong number, since
!   3**3 + 7**3 + 1**3 = 371.
!   ---------------------------------------------------------------

PROGRAM ArmstrongNumber
IMPLICIT NONE

INTEGER :: a, b, c                                    ! the three digits
INTEGER :: abc, a3b3c3                                ! the number and its cubic sum
INTEGER :: Count                                      ! a counter
Count = 0
DO a = 0, 9                           ! for the left most digit
DO b = 0, 9                        !   for the middle digit
DO c = 0, 9                    !     for the right most digit
abc     = a*100 + b*10 + c  !        the number
a3b3c3 = a**3 + b**3 + c**3 !        the sum of cubes
IF (abc == a3b3c3) THEN     !        if they are equal
Count = Count + 1       !           count and display it
WRITE(*,*) 'Armstrong number ', Count, ': ', abc
END IF
END DO
END DO
END DO

END PROGRAM        ArmstrongNumber

PROGRAM INPUT AND OUTPUT
The following is the output from the above program. Thus, there are six Armstrong numbers in the range of 0 and
999.

Armstrong     number     1:   0
Armstrong     number     2:   1
Armstrong     number     3:   153
Armstrong     number     4:   370
Armstrong     number     5:   371
Armstrong     number     6:   407

DISCUSSION

   Three-digit numbers are 000, 001, 002, ..., 009, 010, 011, ..., 019, 020, 021, 022, ..., 099, 100, 101, 102, ...,
109, 110, ... 990, 991, ..., 999. As you can see the right-most digits changes faster than the middle one,
which in turn is faster than the left-most one. As the left-most and the middle digits are fixed to 0 and 0,
the right-most digit changes from 0 to 9. Then, the middle one is increased from 0 to 1. In other words,
whenever the right-most digit completes a 0 to 9 cycle, the middle digit is increased by one and the right-
most digit restart another 0 to 9 cycle. By the same token, whenever the middle digit completes a 0 to 9
cycle, the left-most digit is increased by 1 and the middle digit restarts another 0 to 9 cycle.

Therefore, if a, b and c are the left-most, the middle and the right-most digits, the above
discussion is formalized with the following three nested DO-loops:

DO a = 0, 9
DO b = 0, 9
DO c = 0, 9
... the number is abc .....
END DO
END DO
END DO
   Now, in the inner most DO, the number in hand is abc, where a, b and c are the left-most, middle and the
right-most digits. The number itself is of course a*100 + b*10 + c. The sum of the cubes of the digits is
a**3 + b**3 + c**3. In the program, these two are stored in abc and a3b3c3, respectively.
   Finally, if abc and a3b3c3 are equal, we have found an Armstrong number. We can use abc or a3b3c3

FINDING ALL PRIME NUMBERS IN THE RANGE OF 2 AND N

PROBLEM STATEMENT

In a previous example, we have discussed how to determine if a positive integer is a prime
number. In this one, we shall find all prime numbers in the range of 2 and N, where N is an input
integer.

Write a program to read a value of N, make sure that the value of N is greater than or equal to 2,
and display all prime numbers in the range of 2 and N. In case the value of N is less than 2, your
program should keep asking the user to try again until a value that is greater than or equal to 2 is

SOLUTION
!   ---------------------------------------------------------------
!   This program finds all prime numbers in the range of 2 and an
!   input integer.
!   ---------------------------------------------------------------

PROGRAM Primes
IMPLICIT NONE

INTEGER     :: Range, Number, Divisor, Count

WRITE(*,*) 'What is the range ? '
DO                                                    ! keep trying to read a good input
IF (Range >= 2) EXIT                               ! if it is GOOD, exit
WRITE(*,*) 'The range value must                   be >= 2. Your input = ', Range
WRITE(*,*) 'Please try again:'                     ! otherwise, bug the user
END DO

Count = 1                           ! input is correct. start counting
WRITE(*,*)                          ! since 2 is a prime
WRITE(*,*) 'Prime number #', Count, ': ', 2
DO Number = 3, Range, 2             ! try all odd numbers 3, 5, 7, ...

Divisor = 3                       ! divisor starts with 3
DO
IF (Divisor*Divisor > Number .OR. MOD(Number,Divisor) == 0)                                EXIT
Divisor = Divisor + 2                           ! if does not evenly divide, next odd
END DO

IF (Divisor*Divisor > Number) THEN      ! are all divisor exhausted?
Count = Count + 1              ! yes, this Number is a prime
WRITE(*,*) 'Prime number #', Count, ': ', Number
END IF
END DO

WRITE(*,*)
WRITE(*,*)       'There are ', Count, ' primes in the range of 2 and ', Range

END PROGRAM       Primes

PROGRAM INPUT AND OUTPUT

   The following shows an interaction between the user and program. First, the users type in -10, which is
less than 2. This program displays the input value and a message asking the user to try again. The user
then types in 0, which is still less than 2, causing the same message to occur. The users types in 1 and the
same message appears. Finally, after the user types in 5, the program reports that there are three prime
numbers in the range of 2 and 5, namely: 2, 3, and 5.

What is the range ?
-10
The range value must be >= 2.                  Your input = -10
0
The range value must be >= 2.                  Your input = 0
1
The range value must be >= 2.                  Your input = 1
5

Prime number #1: 2
Prime number #2: 3
Prime number #3: 5

There are 3 primes in the range of 2 and 5

   The following is generated with input 100. There are 25 prime numbers in the range of 2 and 100.

What is the range ?
100

Prime    number     #1:   2
Prime    number     #2:   3
Prime    number     #3:   5
Prime    number     #4:   7
Prime    number     #5:   11
Prime    number    #6: 13
Prime    number    #7: 17
Prime    number    #8: 19
Prime    number    #9: 23
Prime    number    #10: 29
Prime    number    #11: 31
Prime    number    #12: 37
Prime    number    #13: 41
Prime    number    #14: 43
Prime    number    #15: 47
Prime    number    #16: 53
Prime    number    #17: 59
Prime    number    #18: 61
Prime    number    #19: 67
Prime    number    #20: 71
Prime    number    #21: 73
Prime    number    #22: 79
Prime    number    #23: 83
Prime    number    #24: 89
Prime    number    #25: 97

There are 25 primes in the range of 2 and 100

DISCUSSION

   We shall use part of the program shown in a previous example for checking if an integer is a prime
number. Please refer to that example for the details.
   How do we write a bullet-proof program so that the values for N and Range in the program are always
correct? Here is the way our program uses:

WRITE(*,*) 'What is the range ? '
DO
IF (Range >= 2) EXIT
... incorrect input here ...
END DO

It first asks for a number. The actual READ is in the DO-loop. After reading in a value for Range, this value
is checked to see if it is greater than or equal to 2. If it is, EXIT and find prime numbers, since we have
read in a good input. Otherwise, the input is incorrect and the program shows a message and loops back

   After reading in a correct value for Range, we can start prime number searching. Since Range is larger
than or equal to 2, 2 must be included since it is a prime number.
   All the other prime numbers are odd numbers. As a result, we only try to determine if a number in the list
of 3, 5, 7, 9, 11, ...., up to Range, is a prime number. This is, of course, the job of a DO-loop:

DO Number = 3, Range, 2
... determine if Number is a prime number ...
... if Number is a prime number, display it ...
END DO
   The segment in the previous example can be used to replace "...determine if Number is a prime
number..." and the final program is the one shown above.

FINDING ALL PRIME FACTORS OF A POSITIVE INTEGER

PROBLEM STATEMENT

As we have learned in high school, any positive integer can be factorized into prime factors. For
example, 586390350 can be factorized as follows:

Thus, 586390350 has factors 2, 3, 5, 5,, 7, 7, 13, 17, 19 and 19. Note that all factors are prime
numbers.

Write a program that reads in an integer greater than or equal to 2 and finds all of its prime
factors.

This problem is a little more difficult than the others and may require longer time to
understand its logic.

SOLUTION
!   ---------------------------------------------------------------
!   This program determines all prime factors of an n integer >= 2.
!   It first removes all factors of 2. Then, removes all factors
!   of 3, 5, 7, and so on. All factors must be prime numbers since
!   when a factor is tried all of whose non-prime factors have
!   ---------------------------------------------------------------

PROGRAM Factorize
IMPLICIT NONE

INTEGER     :: Input
INTEGER     :: Divisor
INTEGER     :: Count

WRITE(*,*)      'This program factorizes any integer >= 2 --> '

Count = 0
DO                         ! here, we try to remove all factors of 2
IF (MOD(Input,2) /= 0 .OR. Input == 1) EXIT
Count = Count + 1       ! increase count
WRITE(*,*) 'Factor # ', Count, ': ', 2
Input = Input / 2       ! remove this factor from Input
END DO
Divisor = 3                 ! now we only worry about odd factors
DO                          ! 3, 5, 7, .... will be tried
IF (Divisor > Input) EXIT     ! if a factor is too large, exit and done
DO                       ! try this factor repeatedly
IF (MOD(Input,Divisor) /= 0 .OR. Input == 1) EXIT
Count = Count + 1
WRITE(*,*) 'Factor # ', Count, ': ', Divisor
Input = Input / Divisor   ! remove this factor from Input
END DO
Divisor = Divisor + 2    ! move to next odd number
END DO

END PROGRAM Factorize

PROGRAM INPUT AND OUTPUT

   If the input is 100, the output consists of four factors 2, 2, 5 and 5.

This program factorizes any integer >= 2 -->
100

Factor     #   1:   2
Factor     #   2:   2
Factor     #   3:   5
Factor     #   4:   5

   If the input is 16, the output consists of four factors 2, 2, 2 and 2.

This program factorizes any integer >= 2 -->
16

Factor     #   1:   2
Factor     #   2:   2
Factor     #   3:   2
Factor     #   4:   2

   If the input is 53, since it is a prime number, the output has only one factor: 53 itself.

This program factorizes any integer >= 2 -->
53

Factor # 1: 53

   If the input value is 586390350, the output consists of 10 factors 2, 3, 5, 5, 7, 7, 13, 17, 19 and 19.

This program factorizes any integer >= 2 -->
586390350

Factor # 1: 2
Factor # 2: 3
Factor    #   3: 5
Factor    #   4: 5
Factor    #   5: 7
Factor    #   6: 7
Factor    #   7: 13
Factor    #   8: 17
Factor    #   9: 19
Factor    #   10: 19

DISCUSSION

   How to remove a factor from a given number? I believe you have learned it in high school. Let the given
number be n and we know x is a factor of n. Then, we just keep dividing n by x until the quotient is 1 or x
cannot evenly divide n.

For example, 3 is a factor of 72. The first division yields a quotient 24=72/3. The second
division yields a quotient 8=24/3. Thus, the original number 72 has two factors of 3.

If n and x are both 53, then the first division yields a quotient 1=53/53. Since the quotient
is 1, no more division is necessary and 53 has a factor 53!

   So, how to convert the above idea to a program? Let us use Input and Divisor for n and x, respectively.
The following DO-loop will do the job:

DO
IF (MOD(Input,Divisor) /= 0 .OR. Input == 1) EXIT
... since MOD(Input,Divisor)=0 here, Divisor is a factor...
Input = Input / Divisor
END DO

In the above, if Divisor cannot evenly divide Input or Input is 1, we exit the loop. The former condition
states that Divisor is not a factor of Input, while the latter means Input is 1 and does not have any other
factor.

If both conditions are .FALSE., then Divisor can evenly divide Input and Input is not 1.
Therefore, Input is a factor of Divisor. To remove it, just perform a division and this is
the meaning of Input = Input / Divisor.

   Since 2 is the only even prime number, we'd better remove all factors of 2 before starting any other work.
Therefore, letting Divisor to 2 in the above code will remove all factor of 2:

DO
IF (MOD(Input,2) /= 0 .OR. Input == 1) EXIT
... since MOD(Input,2)=0 here, 2 is a factor...
Input = Input / Divisor
END DO

After exiting this loop, we are sure the new value of Input will have no factors of 2. Then, we can try all
odd numbers to see some of them could be factors.
To try odd numbers, it is simply the following:

Divisor = 3
DO
IF (Divisor > Input) EXIT
...remove all factors of Divisor...
Divisor = Divisor + 2
END DO

   Putting everything together, it is the program shown above.
   Why the factors found are prime numbers? A good question, indeed.

It is not difficult to answer, however. If Input does have a composite factor (a composite
number is the product of several prime numbers), say x = a*b, where a is a prime
number. Then, before the program can test if x is a factor, a has been tested since a < x,
and the factor a is removed. Consequently, only a possible factor b remains. In other
words, composite number x is never tested and the program will not report any composite
factors.

   Let us factorize 586390350 as an example:
1. Factors of 2 are removed first. Removing the first factor of 2 yields 293195175=586390350/2.
2. Since 293195175 is not even, it has no more factors of 2. So, we shall try all odd numbers: 3, 5, 7,
9, 11, ...
3. Removing a factor of 3 yields 97731725=293195175/3.
4. Since 97731725 has no factors of 3, try 5.
5. Removing a factor of 5 yields 19546345=97731725/5.
6. Removing a factor of 5 a second time yields 3909269=19546345/5.
7. Since 3909269 has no factors of 5, try 7.
8. Removing a factor of 7 yields 558467=3909269/7.
9. Removing a second factor of 7 yields 79781=558467/7.
10. Since 79781 has no factors of 7, try 9.
11. Since 79781 has no factors of 9, try 11.
12. Since 79781 has no factors of 11, try 13.
13. Removing a factor of 13 yields 6137=79781/13.
14. Since 6137 has no factor of 13, try 15.
15. Since 6137 has no factor of 15, try 17.
16. Removing a factor of 17 yields 361=6137/17.
17. Since 361 has no factor of 17, try 19.
18. Removing a factor of 19 yields 19=361/19.
19. Removing a second factor of 19 yields 1=19/19.
20. Since the quotient is already 1, stop and all factors have been reported.

You might feel this is not a very efficient method since testing if 9 and 15 are factors are
redundant. Yes, you are right; but, this is already a reasonable complicated program for
CS110 and CS201. You could learn more efficient factorization algorithms in other
computer science and/or mathematics courses, since this is an extremely important topic.

HANDLING END-OF-FILE: THE READ STATEMENT REVISITED
In many situations, you really do not know the number of items in the input. It could be so large
to be counted accurately. Consequently, we need a method to handle this type of input. In fact,
you have encountered such a technique in Programming Assignment 1 in which a keyword
IOSTAT= was used in a READ statement. The following is its syntax:

INTEGER :: IOstatus

The third component of the above READ is IOSTAT= followed by an INTEGER variable. The meaning of this new

After executing the above READ statement, the Fortran compiler will put an integer value into
the integer variable following IOSTAT=, IOstatus above. Based on the value of IOstatus, we
have three different situations:

1.   If the value of IOstatus is zero, the previous READ was executed flawlessly and all variables have received
their input values. This is the normal case.
2.   If the value of IOstatus is positive, the previous READ has encountered some problem. In general, without
knowing the system dependent information, it is impossible to determine what the problem was.
However, if hardware and I/O devices are working, a commonly seen problem would be illegal data. For
example, supplying a real number to an integer variable. If IOstatus is positive, you cannot trust the
values of the variables in the READ statement; they could all contain garbage values, or some of them are
fine while the others are garbage.
3.   If the value of IOstatus is negative, it means the end of the input has reached. Under this circumstance,
some or all of the variables in the READ may not receive input values.

What is the end of file? How do we generate it? If you prepare your input using a file, when
you save it, the system will generate a special mark, called end-of-file mark, at the end of that
file. Therefore, when you read the file and encounter that special end-of-file mark, the system
would know there is no input data after this mark. If you try to read passing this mark, it is
considered as an error.

If you prepare the input using keyboard, hiting the Ctrl-D key would generate the end-of-mark
under UNIX. Once you hit Ctrl-D, the system would consider your input stop at there. If your
program tries to read passing this point, this is an error.

However, with IOSTAT=, you can catch this end-of-file mark and do something about it. A
commonly seen application is that let the program to count the number of data items as will be
shown in examples below.

EXAMPLES

    In the following code, the DO-loop keeps reading in three integer values into variables a, b and c. After
executing a READ, if Reason is greater than zero, something was wrong in the input; if Reason is less than
zero, end-of-file has reached. Only if Reason is zero, one can start normal processing.
INTEGER :: Reason
INTEGER :: a, b, c

DO
IF (Reason > 0) THEN
... something wrong ...
ELSE IF (Reason < 0) THEN
... end of file reached ...
ELSE
... do normal stuff ...
END IF
END DO

   The following code keeps reading an integer at a time and adds them to a variable sum. If io is greater
than zero, it displays 'Check input. Something was wrong'; if io is less than zero, it displays the value of
sum. Note that both cases EXIT the DO-loop since continuing the loop execution makes no sense.
Otherwise, the value of x is meaningful and is added to sum.

INTEGER :: io, x, sum

sum = 0
DO
IF (io > 0) THEN
WRITE(*,*) 'Check input. Something was wrong'
EXIT
ELSE IF (io < 0) THEN
WRITE(*,*) 'The total is ', sum
EXIT
ELSE
sum = sum + x
END IF
END DO

Now if the input is

1
3
4

the above code should display 8 (=1+3+4). If the input is

1
@
3

since @ is not a legal integer, the second time the READ is executed, io would receive a positive number
and the above program exits the DO-loop.
COMPUTING ARITHMETIC, GEOMETRIC AND HARMONIC MEANS: REVISITED

PROBLEM STATEMENT

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

Since computing geometric mean requires taking 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.

Unlike a previous example, this program does not know the number of input items and must
handle incorrect input data and ignore them.

SOLUTION
!   -----------------------------------------------------------
!   This program can read an unknown number of input until the
!   end of file is reached. It calculates the arithmetic,
!   geometric, and harmonic means of these numbers.
!
!   This program uses IOSTAT= to detect the following two
!   conditions:
!      (1) if the input contains illegal symbols (not numbers)
!      (2) if the end of input has reached
!   -----------------------------------------------------------

PROGRAM   ComputingMeans
IMPLICIT NONE

REAL      ::   X
REAL      ::   Sum, Product, InverseSum
REAL      ::   Arithmetic, Geometric, Harmonic
INTEGER   ::   Count, TotalValid
INTEGER   ::   IO                        ! this is new variable

Sum            =   0.0
Product        =   1.0
InverseSum     =   0.0
TotalValid     =   0
Count          =   0
DO
IF (IO < 0) EXIT                   ! IO < 0 means end-of-file reached
Count = Count + 1                  ! otherwise, there are data in input
IF (IO > 0) THEN                   ! IO > 0 means something wrong
WRITE(*,*) 'ERROR: something wrong in your input'
ELSE                               ! IO = 0 means everything is normal
WRITE(*,*) 'Input item ', Count, ' --> ', X
IF (X <= 0.0) THEN
WRITE(*,*) 'Input <= 0. Ignored'
ELSE
TotalValid = TotalValid + 1
Sum        = Sum + X
Product    = Product * X
InverseSum = InverseSum + 1.0/X
END IF
END IF
END DO

WRITE(*,*)
IF (TotalValid > 0) THEN
Arithmetic = Sum / TotalValid
Geometric = Product**(1.0/TotalValid)
Harmonic   = TotalValid / InverseSum

WRITE(*,*)           '# of items read -->            ',   Count
WRITE(*,*)           '# of valid items ->            ',   TotalValid
WRITE(*,*)           'Arithmetic mean -->            ',   Arithmetic
WRITE(*,*)           'Geometric mean -->             ',   Geometric
WRITE(*,*)           'Harmonic mean   -->            ',   Harmonic
ELSE
WRITE(*,*)           'ERROR: none of the input is positive'
END IF

END PROGRAM         ComputingMeans

PROGRAM INPUT AND OUTPUT
The input consists of a number of real values, one on each line. The program will count the number of input data
items and ignore those illegal ones.

    If the input data is

1.0
2.0
3.0
4.0
5.0
6.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.
Input    item    6   -->   6.

# of items read -->             6
# of valid items ->             6
Arithmetic mean -->             3.5
Geometric mean -->              2.99379516
Harmonic mean   -->             2.44897938

   The following input contains a few illegal items. The third one is 3.o rather than 3.0. Thus, it is not a legal
real value. The eighth item is #.\$, which is not a number at all. Also, the sixth and tenth are non-positive.

1.0
2.0
3.o
4.0
5.0
-1.0
7.0
#.\$
9.0
0.0

The output is shown below. It correctly identifies all illegal data input items.

Input item 1 --> 1.
Input item 2 --> 2.
ERROR: something wrong in your input
Input item 4 --> 4.
Input item 5 --> 5.
Input item 6 --> -1.
Input <= 0. Ignored
Input item 7 --> 7.
ERROR: something wrong in your input
Input item 9 --> 9.
Input item 10 --> 0.E+0
Input <= 0. Ignored

# of items read -->             10
# of valid items ->             6
Arithmetic mean -->             4.66666651
Geometric mean -->              3.68892741
Harmonic mean   -->             2.72236228

DISCUSSION
   The use of IOSTAT= follows closely the examples discussed in Handling End of File: READ Statement
Revisited.
   This program uses an INTEGER variable IO to keep track the status of a read.
   If the value of IO is negative, end-of-file reached and the program exists the DO-loop.
   If the value of IO is positive, the previous READ had some problem. A message is displayed and asks the
user to try again. In an interactive environment, this is a good practice.
   If the value of IO is zero, we have a normal situation. Then, the program checks further to see if the input
is negative. This is exactly identical to a previous example and hence its discussion is omitted.

THE DO-CYCLE CONSTRUCT AND A PROGRAMMING EXAMPLE

In parallel with the DO-EXIT construct, Fortran has a DO-CYCLE construct as follows:

DO control-info
statements-1
CYCLE
statements-2
END DO
where control-info is empty if the loop is a DO-END DO; otherwise, control-info contains all information that a
counting DO should have.

When the execution of a DO-loop encounters the CYCLE statement, the DO-loop starts next
iteration immediately.

This is not a recommended feature. So, if it is possible, do not use it.

EXAMPLES

   The following loop only displays 1, 2, 4 and 5. If the value of i is 1, 2, 4 or 5, the execution of the loop
enters the ELSE part and displays the value of i. However, if i is 3, since i == 3 is .TRUE., the CYCLE
statement is executed, which brings back to the beginning of the DO-loop starting the next iteration (i.e.,
the iteration corresponds to i=4).

INTEGER :: i

DO i = 1, 5
IF (i == 3) THEN
CYCLE
ELSE
WRITE(*,*) i
END IF
END DO

   The following code has a DO-loop for processing the input value stored in Range. At the beginning of the
loop, the value of Range is read in and checked. If the value is less than 2, the CYCLE statement brings the
control back to the beginning of the loop to read a new value for Range. This will continue until a value
that is greater than or equal to 2. Then, the logical expression of the IF-THEN-END IF is .FALSE. and
consequently the execution continues with "... process Range ...".

INTEGER :: Range

DO
WRITE(*,*) 'An integer >= 2 please --> '
IF (Range < 2) THEN
WRITE(*,*) 'Input not in the required range'
CYCLE
END IF
... process Range ...
END DO

Please compare this example with the technique used in the second prime number example in which EXIT
is used rather than CYCLE.

A PROGRAMMING EXAMPLE
This problem solves a puzzle: RED x FOR = DANGER, where each letter represents a digit and different letters means
different digits. Moreover, R, F and D cannot be zero.

Write a program to find all solutions.

SOLUTION
!   ----------------------------------------------------------
!   This program solve the following puzzle:
!                   RED
!              x    FOR
!              -------
!                DANGER
!   where each distinct letter represents a different digit.
!   Moreover, R, F and D cannot be zero.
!   ----------------------------------------------------------

PROGRAM Puzzle
IMPLICIT NONE

INTEGER :: R, E, D, F, O, A, N, G                     ! the digits
INTEGER :: RED, FOR, DANGER                           ! the constructed values
INTEGER :: Count                                      ! solutions count

WRITE(*,*)      'This program solves the following puzzle:'
WRITE(*,*)
WRITE(*,*)      '    RED'
WRITE(*,*)      'x   FOR'
WRITE(*,*)      '-------'
WRITE(*,*)      ' DANGER'
WRITE(*,*)
Count = 0
DO R = 1, 9
DO E = 0, 9
IF (E == R) CYCLE
DO D = 1, 9
IF (D == R .OR. D == E) CYCLE
DO F = 1, 9
IF (F == R .OR. F == E .OR. F == D) CYCLE
DO O = 0, 9
IF (O == R .OR. O == E .OR. O == D .OR.                                 &
O == F) CYCLE
DO A = 0, 9
IF (A == R .OR. A == E .OR. A == D .OR.                              &
A == F .OR. A == O) CYCLE
DO N = 0, 9
IF (N == R .OR. N == E .OR. N == D .OR.                            &
N == F .OR. N == O .OR. N == A) CYCLE
DO G = 0, 9
IF (G == R .OR. G == E .OR. G == D .OR.                          &
G == F .OR. G == O .OR. G == A .OR.                         &
G == N) CYCLE
RED     = R*100 + E*10 + D
FOR     = F*100 + O*10 + R
DANGER = D*100000 + A*10000 + N*1000 + G*100                     + E*10 + R
IF (RED * FOR == DANGER) THEN
Count = Count + 1
WRITE(*,*) 'Solution ', Count, ':'
WRITE(*,*) '      RED = ', RED
WRITE(*,*) '      FOR = ', FOR
WRITE(*,*) ' DANGER = ', DANGER
WRITE(*,*)
END IF
END DO
END DO
END DO
END DO
END DO
END DO
END DO
END DO

END PROGRAM Puzzle

PROGRAM OUTPUT
The following is the output generated by the above program. There are two solutions:

This program solves the following puzzle:

RED
x    FOR
-------
DANGER
Solution     1:
RED     = 321
FOR     = 563
DANGER     = 180723

Solution     2:
RED     = 481
FOR     = 364
DANGER     = 175084

DISCUSSION

   This program uses a brute-force method. That is, it searches all possibilities.
   Since there are eight digits, R, E, D, F, O, A, N and G, each of which runs from 0 to 9 except for R, F and D
which runs from 1 to 9, we need eight nested DO-loops.
   Since different letters represent different digits, at the very beginning of a DO-loop, we must make sure
the value of its control variable is different from the values of all previous loops.

DO R = 1, 9
DO E = 0, 9
IF (E == R) CYCLE
DO D = 1, 9
IF (D == R .OR. D == E) CYCLE
... other loops ...
END DO
END DO
END DO

The above only shows three loops for R, E and D. At the beginning of the E loop, the value of E is checked
to see if it is equal to the value of R. If they are equal, the CYCLE brings the control to the next iteration.
Similarly, at the beginning of the D loop, the value of D is compared against the values of E and R. If they
are equal, CYCLE causes the start of the next iteration. Note that D runs from 1 to 9.

   In the inner-most loop, the value of RED, FOR and DANGER are computed and compared. If RED*FOR is
equal to DANGER, a solution is found and its values are displayed.

RED     = R*100 + E*10 + D
FOR     = F*100 + O*10 + R
DANGER = D*100000 + A*10000 + N*1000 + G*100 + E*10 + R
IF (RED * FOR == DANGER) THEN
... display READ, FOR and DANGER ...
END IF

   The concept of this program, except for the use of CYCLE, is similar to that of finding all three-digit
Armstrong Numbers. Please compare these two programs.

```
To top