0% found this document useful (0 votes)
21 views

7- Scientiffic Computer Language (Phy 435)

Uploaded by

fegoooo44
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views

7- Scientiffic Computer Language (Phy 435)

Uploaded by

fegoooo44
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 146

Mansoura University

Faculty of Science
Physics Department

Fortran Language
(Programming)
For
B.Sc. Students (Phys 435)
Mansoura University
Faculty of Science
Physics Department

FORTRAN LANGUAGE
(PROGRAMMING)
For
B. Sc. Students

0
CONTENTS

1- INTRODUCTION.....................................................................1
2- DATA TYPES AND OPERATIONS ....................................... 4
3- CONTROL STATEMENTS..................................................... 40
• IF statement..........................................................................40
• S E L E C T CASE statement .............................................49
• DO Loops .........................................................................58
4- FUNCTIONS AND SUBROTINES SUBPROGRAMS.............79
5- ARRAYS.................................................................................... 101
6- OUTPUT DESIGN AND FILE PROCESSING.........................117

i
1. Introduction:
1.1 What is Fortran?
FORTRAN (FORmula TRANslation) was developed in the fifties as a
programming language for scientific and engineering applications. In 1966 the
language was standardized and FORTRAN IV was born. It was updated a number
of times in order to remain competitive with more contemporary programming
languages. FORTRAN 77 was released in 1978, followed by FORTRAN 90 in
1991, updated in 1997 to Fortran 95 and further updated in 2004 to Fortran 2003,
and in 2010 to Fortran 2008 and updated in 2018 to Fortran 2018. FORTRAN
90 we will be using in this course.
High level language instructions are not executable. Instead, a high-level
language source program is read as input by a program called a compiler, which
checks its syntax and, if it is free from errors, compiles an equivalent machine
code object program.

Although it is in machine code, the object program is incomplete because


it includes references to subprograms which it requires for such common tasks
as reading input, producing output and computing mathematical functions. These
subprograms are grouped together in libraries which are available for use by all
object programs. To create an executable program, the object program must be
linked to the subprogram libraries it requires. The executable program may then
be loaded into memory and run. The steps required to compile, link and run a
Fortran program are illustrated by Figure 1.

1
FORTR Link
FORTRA AN with Executab
N Compil Librari le File
Program er es

Executable
Source Code Object Code
Code Librari
es

Make
Test &
Change Execute
s Debug
Program Program
in
Sourc
Figure 1: Compiling, linking and running a Fortran program

Portability

A major advantage Fortran has is that it is standardized by ANSI (American


National Standards Institute) and ISO (International Standards Organization).
Consequently, if your program is written in ANSI Fortran 90 then it will run on
any computer that has a Fortran 90 compiler. Thus, Fortran programs are portable
across computer platforms

1.2. Fortran Basics


Program organization
A Fortran program generally consists of a main program and possibly several
subprograms . For now, we will assume all the statements are in the main
program; subprograms will be treated later. The basic form of a Fortran 90 program
is as follows:

PROGRAM program-name

declarations
statements
stop
END PROGRAM program-name

Using any editor, a programmer writes his/ here program in a file. A


Fortran program is just a sequence of lines of text. The text has to follow a certain

2
syntax to be a valid Fortran program. We start by looking at a simple example
where we calculate the area of a circle:
PROGRAM circle_area
IMPLICIT NONE
! reads a value representing the radius of a circle,
! then calculates and writes out the area of the circle.
REAL :: radius, area
REAL, PARAMETER :: pi=3.141592
READ (*,*) radius
area = pi*radius*radius
WRITE (*,*) area
END PROGRAM circle_area

Basic program structure

• Free-form source code is allowed. Statements may begin in any column.


• A statement must start with a new line.
• Fortran 90 allows both upper and lowercase letters.
• a program starts with program program_name
• it ends with end program program_name
• Lines may extend to 132 characters.
• More than one statement may be placed on a line. A semicolon (;) is used as
the delimiter to separate statements. For example:

height = x*SIN(theta); Area = 0.5*y*height

Comments
Comments may appear anywhere in the program. Well-written comments are
crucial to program readability.
• In-line comments are allowed. These comments begin with an exclamation
point (!) and extend to the end of the line.
• Everything following ! will be ignored.
• The exclamation mark may appear anywhere on a line.
for example:

! This is an example
!
PROGRAM Comment
..........
READ(*,*) Year ! read in the value of Year
..........
Year = Year + 1 ! add 1 to Year
..........
END PROGRAM Comment

3
Continuation Lines
• If a statement is too long to fit on one line, it has to be continued.
• The continuation character is &, which is not part of the statement.
For example:

Total = Total + &


Amount * Payments
! Total = Total + Amount*Payments
area = 3.14159265358979 &
* r * r
! area = 3.14159265358979 * r * r

Blank spaces
Blank spaces are ignored in Fortran. So, if you remove all blanks in a Fortran
program, the program is still syntactically correct but almost unreadable for
humans.

Each program should end with the “END” statement. This signifies the
physical end of the program. The STOP statement signals the logical end of the
program. While the END statement appears at the end of the program, the STOP
statement may appear anywhere in the program, possibly, to stop execution of the
program under certain conditions. The compiler sequentially executes each
statement in the program.

2. DATA TYPES AND OPERATIONS


Data can be of different types. The basic data types in FORTRAN are: integer,
real, complex, character, and logical. In this chapter we present these types in
detail.

2.1 Constants
A constant is a fixed value of a data type that cannot be changed.
2.1.1 Integer Constants
Integer constants are whole numbers. An integer constant does not have a
decimal point. Examples of integer constants are:

4
32 0 -6201 27 -83 1992
2.1.2 Real Constants
A real constant is a constant number that has a decimal point. Examples of real
constants are 1.23, -0.0007, 3257.263, 5.0, 0.00002, 18., 774.00000, -64.9899 and
94000000000000000.0. The last number in the previous example leads us to the
scientific notation for real numbers. 94000000000000000.0 can be written as 9.4
x 1016 or as 0.94 x 1017. In FORTRAN, this number can be written in two possible
ways: as 94000000000000000.0, or in scientific notation as 9.4E16 or 0.94E+17.
2.1.3 Complex number
a complex number has a real and an imaginary component. Complex numbers in
Fortran as a pair of real numbers (real part first, followed by the imaginary part).

For example, the complex number (3.0, -5.0) is equal to 3.0 – 5.0i
2.1.4 Logical Constants
There are two logical constants; true and false. In FORTRAN, the logical constant
true is written as .TRUE. and the logical constant false is written as .FALSE..

2.1.5 Character Constants


Character constants must be placed between two consecutive single quotes ( ' ' ).
A character constant is also referred to as a character string. The following table
shows some character constants and their representation in FORTRAN:
Character Constant FORTRAN Representation
THIS IS CHAPTER TWO 'THIS IS CHAPTER TWO'
MORE THAN ONE BLANK 'MORE THAN ONE BLANK'
ISN'T IT? 'ISN''T IT?'
1234 AS CHARACTERS '1234 AS CHARACTERS'

Note that if a single quote ( ' ) needs to be included in a character constant, it


should be written as two single quotes.

2.2 Variables
A variable is an object of a certain data type that takes a value of that type. A
variable, as the name suggests, can change its value through certain FORTRAN

5
statements such as the assignment statement and the READ statement. We shall
use the term variable to mean variable name. There are some rules for choosing
variable names in FORTRAN. These rules are as follows:
• Variable names may consist of up to 31 characters.
• The first character of a variable name must be a letter.
Valid characters include all letters, digits, and the underscore symbol ( _ ).
• A variable should not contain special characters ($, ;, ,, :, !, ~, ^,(,{, [, ), }, ],
<, >, ?, “, „, \, | , @, %, &, #, +, -,/,*, .., etc.).
• A variable should not contain blanks.
Examples of valid and invalid variable names are given below:
Variable Comment
TRY Valid.
NAME21 Valid.
name_all Valid.
A+B Invalid. Special character '+' can not be used.
5TEST Invalid. Name does not start with a letter.
FIVE7 Valid.
The following subsections present different variable types and how to define
them.
2.2.1 Implicit Declaration
Fortran 90 permits variables to be typed and declared implicitly, that is
without using a variable declaration as given above. An implicit declaration is
performed whenever a name appears which has not been explicitly declared and
the program section does not contain the statement IMPLICIT NONE.
The command IMPLICIT NONE is allowed. This feature cancels the default
naming convention. When invoked, program variables MUST be specified
explicitly.
Declaring the type of a Fortran variable is done with type statements. It has the
following form:
type-specifier :: list

6
where the type-specifier is one of the following and list is a list of variable
names separated with commas:
• INTEGER :: the variables in list can hold integers
• REAL:: the variables in list can hold real numbers
• COMPLEX:: the variables in list can hold complex numbers
• LOGICAL:: the variables in list can hold logical values
(i.e., true or false)
• CHARACTER:: the variables in list can hold character strings
2.2.2 Integer Variables
Integer variables can hold only integer values. There are two ways to define an
integer variable in FORTRAN: explicitly and implicitly. The explicit definition
allows us to define variable types, irrespective of the first letter of the variable
name. In such a case, we must use the INTEGER statement. The general form
of this statement is as follows:
INTEGER :: list of integer variables

where list of integer variables is a list that has the names of variables separated
by commas. The INTEGER statement is a FORTRAN declaration statement.
This statement must be appeared at the beginning of the program before any other
executable statement. In fact, all declaration statements must appear at the
beginning of the program. The following examples demonstrate the use of the
INTEGER statement:
Example Comments
INTEGER :: BOOKS, NUM, X Three integer variables: BOOKS, NUM, X
INTEGER :: Y1, AB3W Two integer variables: Y1, AB3W
INTEGER:: CLASS, ID, TOTAL Three integer variables: CLASS, ID, TOTAL
INTEGER :: SUM One integer variable: SUM
In implicit definition, we choose a variable name that starts with one of the
following letters: I, J, K, L, M, N. Hence, any variable that starts with one of
these letters is considered implicitly as an integer variable unless it is otherwise

7
explicitly stated. Examples of integer variables are:
NUMB, N1, LAB, ISUM, JX, KILO, MEMO.
Implicit definition is assumed when a programmer forgets to use explicit
definition.

2.2.3 Real Variables


Real variables can hold only real values. As was the case in integer variable
definition, there are two ways to define a real variable: explicitly and implicitly.
The explicit definition allows us to define variable types irrespective of the first
letter of the variable name, using the REAL statement. The general form of this
statement is as follows:
REAL :: list of real variables
where list of real variable is a list that has the names of variables separated by
commas. The REAL statement is a FORTRAN declaration statement. It must be
appeared in the beginning of the program before any other executable statement.
The following examples demonstrate the use of the REAL statement:
Example Comments
REAL :: NOTES, NUM2, IX Three real variables: NOTES, NUM2, IX
REAL :: M1, AB3 Two real variables: M1, AB3
REAL :: INSIDE, KD2, SBTOT Three real variables: INSIDE, KD2, SBTOT
REAL :: J1SUM One real variable: J1SUM

We should try our best to declare our variables explicitly. If we forget to use
explicit definition, then FORTRAN compilers assume implicit definition. In
implicit definition, any variable that does not start with one of the letters I, J, K,
L, M, N is considered, implicitly, as a real variable unless the type of the variable
is explicitly stated. Examples of real variables are:
YNUMB, X1, PERC, SUM, RJX, TOTAL, STID, A5, EPSLON, PI.

8
2.2.4 Parameters
The term parameter in Fortran refers to a value which will be constant, for
example the programmer will want the value of pi to be unaltered during a
program. Therefore, pi may be defined as

REAL, PARAMETER :: pi=3.141592

The word REAL defines the type of pi and the word PARAMETER is an attribute
of the REAL object which is known as pi and has the value 3.141592. Parameters
may also be defined for other data types, for example:
INTEGER, PARAMETER :: maxvalue=1024
INTEGER, PARAMETER :: repeatcount=1000
The objects declared to be parameters may not be altered in the program.
2.2.5 Complex Variables
Fortran allows variables to be declared as complex numbers. Variables such as
this are declared with their first value as the real component and the second
as the imaginary. The following statements show an example of a complex
variable declaration in a portion of a program.
COMPLEX:: the variables in list can hold complex numbers
where list of real variable is a list that has the names of variables separated by
commas. The COMPLEX statement is a FORTRAN declaration statement. It
must be appeared in the beginning of the program before any other executable
statement.
The following program demonstrates complex number arithmetic −
program ComplexArithmatic
implicit none

complex, parameter :: i = (0, 1) ! sqrt(-1)


complex :: x, y, z

x = (7, 8);
y = (5, -7)
write(*,*) i * x * y

9
z=x+y
write(*,*) "z = x + y = ", z

z=x-y
write(*,*) "z = x - y = ", z

z=x*y
write(*,*) "z = x * y = ", z

z=x/y
write(*,*) "z = x / y = ", z

end program ComplexArithmatic

When you compile and execute the above program it produces the following result-
(9.00000000, 91.0000000)
z = x + y = (12.0000000, 1.00000000)
z = x - y = (2.00000000, 15.0000000)
z = x * y = (91.0000000, -9.00000000)
z = x / y = (-0.283783793, 1.20270276)
Complex Type
The generic function cmplx() creates a complex number. It produces a result who’s
real and imaginary parts are single precision, irrespective of the type of the input
arguments.

program createComplex
implicit none

integer , parameter :: i = 10
real, parameter :: x= 5.17
print *, cmplx(i, x)

end program createComplex

When you compile and execute the above program it produces the following result-
(10.0000000, 5.17000008)

2.2.6 Logical Variables


Logical variables have either a .TRUE. or a .FALSE. value. There is only one
way to define logical variables - they must be declared explicitly. The statement
that is used to define logical variables is the declarative LOGICAL statement. It
must appear at the beginning of the program before any executable statement.
The general structure of the LOGICAL statement is:
LOGICAL :: list of logical variables

10
where list of logical variables is one or more variables separated by commas.
Examples of LOGICAL statement usage are given below:
Example Comments
LOGICAL:: TEST, FLAG, Q, P Four logical variables: TEST, FLAG, Q, P
LOGICAL:: M5 One logical variable: M5
LOGICAL:: SORTED, LINK Two logical variables: SORTED, LINK

2.2.7 Character Variables


Type CHARACTER is more involved. Since a string has a length attribute, a
length value must be attached to character variable declarations. The declaration
statement that is used in character definition is the CHARACTER statement. As
is the case in other types of declaration statements, the CHARACTER declaration
statement must appear at the beginning of the program and should be typed before
any executable statement. There are two ways to do this:
• Use CHARACTER(LEN=i) to declare character variables of length i. For
examples,
o Name and Street are character variables that can hold a string of no
more than 15 characters:
o CHARACTER(LEN=15) :: Name, Street
• Use CHARACTER(i) to declare character variables of length i. That is,
there is no LEN= in the parenthesis. For examples,
o Name and Street are character variables that can hold a string of no more
than 15 characters:
o CHARACTER(15) :: Name, Street
• If a variable can only hold a single character, the length part can be removed.
The following three declarations are all equivalent:
CHARACTER(LEN=1) :: letter, digit
CHARACTER(1) :: letter, digit
CHARACTER :: letter, digit

Here, variables letter and digit can only hold no more than one character.

11
• If you want to declare character variables of different length with a single
statement, you can attach a length specification, *i, to the right of a variable.
In this case, the corresponding variable will have the indicated length and all
other variables are not affected.
• CHARACTER(LEN=10) :: City, Nation*20, BOX, bug*1
Here, variables City and BOX can hold a string of no more than 10
characters, Nation can hold a string of no more than 20 characters,
and bug can hold only one character.
• There is one more way of specifying the length of a character variable. If the
length value is replaced with a asterisk *, it means the lengths of the declared
variables are determined elsewhere. In general, this type of declarations is
used in subprogram arguments or in PARAMETER and is refereed to
as assumed length specifier.
• CHARACTER(LEN=*) :: Title, Position
Here, the actual lengths of variables Title and Position are unknown and will
be determined elsewhere.

2.3 Arithmetic Operations


Addition, subtraction, multiplication, division, and exponentiation (power) are
called arithmetic operations. The following subsections present details about
these operations.

2.3.1 Arithmetic Operators


In FORTRAN there are five basic operators. These operators are shown in the
following table with the sequence in which they are evaluated (precedency):

12
FORTRAN Operation FORTRAN Math Precedency
Operator Example Notation
** Exponentiation X ** Y xy 1
* Multiplication X*Y x  y 2
/ Division X/Y xy 2
+ Addition X+Y x+y 3
- Subtraction X-Y x-y 3

In any arithmetic expression, parentheses have the highest priority


(precedence) in evaluation. In the case of nested parentheses (parentheses inside
parentheses), evaluation starts with the most-inner parentheses. The next higher
priority operator is the exponentiation (also called power) operator '**'. If there
are two or more consecutive exponentiation operators in an arithmetic expression,
evaluation of these exponentiation operations is done from right to left. For
example, in the expression 2**2**3, we start evaluating 2**3 (which is 8) and
after that we evaluate 2**8 (which is 256). Division and multiplication operators
have the same priority, but they are lower in priority than the exponentiation
operator. The addition and subtraction operators have the same priority which is
lower than the priority of multiplication and division operators. Operators with
the same priority are evaluated from left to right with the exception of the
exponentiation operator as explained earlier. There are two restrictions on the
use of arithmetic operators. The first restriction is that no two operators must
appear consecutively. For example, if the expression 2 * -3 is intended, in
FORTRAN, it should be written as 2*(-3). The second restriction is on the use of
the exponentiation operator. This operator must not be used to raise a negative
number to a real exponent. For example, expressions such as (-2.0) ** 1.5 or (-3)
** 2.3 are not allowed in FORTRAN language. To compute, when is real, most
FORTRAN Compilers use the mathematical formula. When is negative, the value
of is undefined?

13
2.3.2 Integer Operations

An operator between two integer operands is considered to be an integer operator


and the operation is considered to be an integer operation. Integer operations
always produce integer results. The fraction part is ignored. The following table
shows some examples of integer operations:
Expression Value Comment
50 - 23 27
3 ** 2 9
5*7 35
8/2 4
8/3 2 Fraction part is truncated (not 2.6666667)
9 / 10 0 Fraction part is truncated (not 0.9)

Note that the expression I/J * J is not always equivalent to I. For example, if I
and J are integer variables, and the value of I is 17 and the value of J is 6, the
expression becomes 17 / 6 * 6. To evaluate this expression, we consider operator
precedence. Since operators '/' and '*' have the same priority, they are evaluated
from left to right. We start with 17 / 6. The two operands are integers and therefore
'/' here is an integer operator. The result must be an integer, which in this case
evaluates to 2. Now, evaluation proceeds as 2 * 6 which results in 12 and not 17.

2.3.3 Real Operations


An operator between two real operands is considered to be a real operator and the
operation is considered to be a real operation. Real operations produce real
results. The following table shows some examples of real operations:
Expression Value
50.0 - 23.0 27.0000000
3.0 ** 2.0 9.0000000
5.0 * 7.0 35.0000000
8.0 / 2.0 4.0000000
8. / 3.0 2.6666667
9. / 10. 0.9000000
9.3 / 3.2 2.9062500
2.3.4 Mixed-mode Operations

14
An operator between an integer operand and a real operand is considered to be a
mixed-mode operator and the operation is considered to be a mixed-mode
operation. Mixed-mode operations produce real results. The following table
shows examples of mixed-mode operations:
Expression Value Comment
50 - 23.0 27.0000000
3.0 ** 2 9.0000000
3 ** 2.0 9.0000000
4** 0.5 2.0000000
5.0 * 7 35.0000000
56.7 / 7 8.1000000
8 / 2.0 4.0000000
8.0 / 3 2.6666667
9 / 10. 0.9000000 Decimal point can be placed without zero.
17 / 6 * 6.0 12.0000000 '/' is an integer operator and '*' is a mixed mode
operator

The number of positions to the right of the decimal point in a real number
depends on the computer used. In the examples above, we have assumed that the
computer allows up to 7 positions.
2.3.5 Examples
Example 1: Evaluate the following arithmetic expression
20 - 14 / 5 * 2 ** 2 ** 3
Solution:
Expression: 20 - 14 / 5 * 2 ** 2 ** 3
Priority is for ** from right to left
Step 1: 2 ** 3 = 8 (integer operation)
Expression: 20 - 14 / 5 * 2 ** 8
Priority is for ** from right to left
Step 2: 2 ** 8 = 256 (integer operation)
Expression: 20 - 14 / 5 * 256
Priority is for / and * from left to right
Step 3: 14 / 5 = 2 (integer operation)
Expression: 20 - 2* 256
Priority is for *
Step 4: 2 * 256 = 512 (integer operation)
Expression: 20 – 512
Priority is for –
Result: -492

Example 2: Evaluate the following arithmetic expression

15
14.0 / 5 * (2 * (7 - 4) / 4) ** 2
Solution:
Expression: 14.0 / 5 * (2 * (7 - 4) / 4) ** 2
Priority is for expression inside the inner most parenthesis
Step 1: (7 - 4) = 3 (integer operation)
Expression: 14.0 / 5 * (2 * 3 / 4) ** 2
Priority is for expression inside the parenthesis
Step 2 & 3: (2 * 3 / 4) = (6 / 4) = 1 (2 integer operations)
Expression: 14.0 / 5 * 1 ** 2
Priority is for **
Step 4: 1 ** 2 = 1 (integer operation) Expression: 14.0 / 5 * 1
Priority is for / and * from left to right
Step 5: 14.0 / 5 = 2.8000000 (Mixed mode operation)
Expression: 2.8000000 * 1
Priority is for *
Result: 2.8000000
Example 3: Rewrite the following FORTRAN expression as a mathematical
form X+Y/W–Z
Solution:
y
x+ −z
w

Example 4: Rewrite the following FORTRAN expression as a mathematical


form X ** (1.0 / 2.0) / Y ** Z
Solution:
1
2
x x
z
or
y yz

Example 5: Convert the following mathematical expression into FORTRAN


expression. Use minimum number of parenthesis
a +b
a −b 2
2

Solution: (A + B) ** 0.5 / (A ** 2.0 - B ** 2.0)

2.4- Intrinsic Functions

16
These are predefined functions that are available from the FORTRAN language.
Certain functions, such as the trigonometric functions, are frequently encountered
in programming. Instead of developing them repeatedly in each program. A list
of commonly used intrinsic functions is given below.

Function Meaning

ABS(x) absolute value of x

SQRT(x) square root of x


SIN(x) sine of x radian
COS(x) cosine of x radian
TAN(x) tangent of x radian
ASIN(x) arc sine of x
ACOS(x) arc cosine of x
ATAN(x) arc tangent of x
EXP(x) exp(x)
LOG(x) natural logarithm of x

• Note that all trigonometric functions use radian rather than degree for
measuring angles. For function ATAN(x), x must be in (-PI/2, PI/2).
For ASIN(x) and ACOS(x), x must be in [-1,1].
• Conversion functions:

Function Meaning
INT(x) integer part x
NINT(x) nearest integer to x
FLOOR(x) greatest integer less than or equal to x
FRACTION(x) the fractional part of x
REAL(x) convert x to REAL

17
• Other functions:

Function Meaning

MAX(x1, x2, ..., xn) maximum of x1, x2, ... xn

MIN(x1, x2, ..., xn) minimum of x1, x2, ... xn

MOD(x,y) remainder x - INT(x/y)*y

The example below has three initialized variables A, B and C. The result is
computed and saved into uninitialized variable R.

REAL :: A = 1.0, B = -5.0, C = 6.0


REAL :: R
R = (-B + SQRT(B*B - 4.0*A*C))/(2.0*A)
The result of output:
R = 3.0.

Examples:
1. INT(-3.5) = -3
2. NINT(3.5) = 4
3. NINT(-3.4) = -3
4. FLOOR(3.6) = 3
5. FLOOR(-3.5) = -4
6. FRACTION(12.3)= 0.3
7. REAL(-10) = -10.0
8. MOD(4,3) = 1

2.5 Logical Operations


Fortran has five LOGICAL operators that can only be used with expressions
whose results are logical values (i.e., .TRUE. or .FALSE.). These five logical
operators are
.NOT. : logical not
.AND. : logical and
.OR. : logical or
.EQV. : logical equivalence
.NEQV. : logical not equivalence

18
• The logical operator .AND., requires two expressions or variables and
gives a .TRUE.result only if both expressions are true, otherwise evaluates
to .FALSE.. Consider the following example:
LOGICAL :: test, employed=.true.
INTEGER :: age=50
...
test = employed .AND. (age<45) !test=.false.

There are two sub-expressions here, one .TRUE.the other .FALSE.hence the
result is .FALSE..
• The logical operator .OR. requires two expressions or variables and gives
the value .TRUE. if either one of the expressions is true, and .FALSE.
otherwise. Consider the following example:
LOGICAL :: test
CHARACTER(LEN=10) :: name = `James`
...
test = (name='Dimitris') .OR. (name='James') !test=.true.

• The logical operator .NOT. is used to invert the logical value of an


expres- sion, i.e. .TRUE.becomes .FALSE.and vice versa. For example:
INTEGER :: big=100, small=2
LOGICAL :: test
...
test = .NOT. (big>small) !test=.false.
test = .NOT. test !test=.true.

where the statement enclosed by the (optional) brackets is assigned a value


which in turn is inverted.

• The logical equivalence operator .EQV. is used to check if all variables


or expressions have the same logical value (can be either .TRUE. or
.FALSE.). If both values are the same the whole expression evaluates to
.TRUE., otherwise it evaluates to .FALSE..
For example:

19
LOGICAL :: test
...
test = (5*3>12) .EQV. (6*2>8) !test=.true.
test = (5*3<12) .EQV. (6*2<8) !test=.true.
both statements evaluate to .TRUE. because the sub-expressions in each
statement take the same logical values.
• The logical non-equivalence operator .NEQV. is used to evaluate
expressions to .TRUE. only if one of the expressions has a different logical
value to the other(s), otherwise evaluates to .FALSE..
For example:

LOGICAL :: test
...
test = (5*3>12) .NEQV. (6*2>13) !test=.true.
test = (5*3>12) .NEQV. (6*2<13) !test=.false.
the first expression has one true and one false component and therefore evaluates
to .TRUE., the second expression has two true components and therefore
evaluates to .FALSE..
The following table shows the results of the five logical operations .AND., .OR.,
.NOT. , .EQV. and .NEQV on different operand values, assuming P and Q are
logical variables:
P Q P .AND. Q P. OR. Q .NOT. P P. EQV. Q P. NEQV. Q
.FALSE. .FALSE. .FALSE. .FALSE. .TRUE. .TRUE. .FALSE.
.FALSE. .TRUE. .FALSE. .TRUE. .TRUE. .FALSE. .TRUE.
.TRUE. .FALSE. .FALSE. .TRUE. .FALSE. .FALSE. .TRUE.
.TRUE. .TRUE. .TRUE. .TRUE. .FALSE. .TRUE. .FALSE.

• The .NOT. operator has the highest priority of the three logical operators
followed by the .AND. operator and .OR. operator. The .EQV. operator and
.NEQV. has the lowest priority. These operators are shown in the following
table with the sequence in which they are evaluated (precedency):

20
Logical Operator Precedence
.NOT. 1
.AND. 2
.OR. 3
.EQV. 4
.NEQV. 4

Example 1: Evaluate the following logical expression:


.FALSE. .OR. .NOT. .TRUE. .AND. .TRUE.
Solution:
Expression: .FALSE. .OR. .NOT. .TRUE. .AND. .TRUE.
priority is for .NOT.
Step 1: .NOT. .TRUE. is .FALSE.
Expression: .FALSE. .OR. .FALSE. .AND. .TRUE.
priority is for .AND.
Step 2: .FALSE. .AND. .TRUE. is .FALSE.
Expression: .FALSE. .OR. .FALSE.
priority is for .OR.
Result: .FALSE.

Example 2: Assume that the following declaration is given:


LOGICAL:: FLAG
If it is known that the expression
.NOT. FLAG .OR. .FALSE.
has the value .TRUE., what is the value of FLAG?
Solution: The final result must be .TRUE.. The last step is somevalue .OR.
.FALSE. because the .NOT. operator has higher priority than the .OR. operator.
somevalue .OR. .FALSE. will have the value .TRUE. if and only if the value of
somevalue is .TRUE.. But somevalue is equivalent to .NOT. FLAG, therefore the
value of FLAG is .FALSE..

2.5.1 Relational Operators


There are six relational operators:
The values of arithmetic expressions can be compared using relational operators.
The following table shows the different symbolic forms of the relational operators
are allowed:

21
Operator Operator
Fortan77 Fortan90
.EQ. == : equal to
.NE. /= : not equal to
.GT. > : greater than
.GE. >= : greater than or equal to
.LT. < : less than
.LE. <= : less than or equal to

Here are important rules:


• Each of these six relational operators takes two operands. These two operands
must both be arithmetic or both be strings. For arithmetic operands, if they are
of different types (i.e., one INTEGER and the other REAL), the INTEGER
operand will be converted to REAL.
• A relational expression evaluates to either .TRUE. or .FALSE..
For example, 5 /= 3 is .TRUE. and 7 + 3 >= 20 is .FALSE.
• All relational operators have equal priority and are lower than those of
arithmetics operators as shown in the table below:

Type Operator Associativity

** right to left

Arithmetic * / left to right

+ - left to right

Relational < <= > >= == /= none

• This means that a relational operator can be evaluated only if its two operands
have been evaluated. For example,
in a + b /= c*c + d*d
expressions a+b and c*c + d*d are evaluated before the relational
operator /= is evaluated.

22
• If you are not comfortable in writing long relational expressions, use
parenthesis. Thus,
3.0*SQRT(Total)/(Account + Sum) - Sum*Sum >= Total*GNP - b*b
is equivalent to the following:
(3.0*SQRT(Total)/(Account + Sum) - Sum*Sum) >= (Total*GNP - b*b)
• Although a < b < c is legal in mathematics, you cannot write comparisons this
way in Fortran. The meaning of this expression is a < b and b < c. You should
use logical operator to achieve this.
Examples:
i. 3**2 + 4**2 == 5**2 is .TRUE.
ii. If the values of REAL variables a, b and c are 1.0, 2.0 and 4.0, respectively,
then b*b - 4.0*a*c >= 0.0 is equivalent to 2.0*2.0 - 4.0*1.0*4.0 >= 0.0, which
evaluates to -12.0 >= 0.0. Thus, the result is .FALSE.
iii. If REAL variables x and y have values 3.0 and 7.0, and INTEGER
variables p and q have values 6 and 2, what is the result of
x*x - y*y + 2.0*x*y /= p*q + p**3 - q**3?
Solution:
x*x - y*y + 2.0*x*y /= p*q + p**3 - q**3
--> 3.0*3.0 - 7.0*7.0 + 2.0*3.0*7.0 /= 6*2 + 6**3 - 2**3
--> ([3.0*3.0] – (7.0*7.0) + ((2.0*3.0)*7.0)) /= (((6*2) + (6**3)) – (2**3))
--> 2.0 /= 220.0
--> .TRUE.
The next subsection presents the use of relational, logical, and arithmetic
operators in logical expressions.

2.5.2 Logical Expressions

Fortran has four types of operators: arithmetic, relational, logical,


and character. The following is a table of these operators, including their priority
and associativity.

23
Type Operator Associativity
** right to left
Arithmetic * / left to right
+ - left to right
Relational < <= > >= == /= none
.NOT. right to left
.AND. left to right
Logical
.OR. left to right
.EQV. .NEQV. left to right

Some Useful Notes:


• In the table, the operator on the top-most row (**) has the highest priority (i.e., it
will be evaluated first) while the operators on the bottom-most row
(i.e., .EQV. and .NEQV.) have the lowest priority. The operators on the same row
have the same priority. In this case, the order of evaluation is based on their
associativity law.
• In addition to addition +, subtraction -, multiplication * and division /, Fortran
has an exponential operator **. Thus, raising X to the Y-th power is written
as X**Y. For example,
the square of 5 is 5**2, and the square root of 5 is 5**0.5. The exponential
operator has the highest priority.
• Operators + and - can also be used as unary operators, meaning that they only
need one operand. For example, -A and +X. The former means change the sign
of A, while the latter is equivalent to X.
• Unary operators + and - have the same priority as their binary counterparts (i.e.,
addition + and subtraction -). As a result, since ** is higher than the negative
sign -, -3**2 is equivalent to -(3**2), which is -9.
• For arithmetic operators, the exponential operator ** is evaluated from right to
left. Thus, A**B**C is equal to A**(B**C) rather than (A**B)**C
The following examples demonstrate the evaluation of logical expressions:

24
Example 1: Given that X has a value of 3.0, Y has a value of 5.0, Z has a value
of 10.0, and FLAG is a logical variable with .FALSE. value, evaluate the
following FORTRAN expression:
.NOT. FLAG .AND. X*Y> Z .OR. X+Y > Z
Solution:
Expression: .NOT. FLAG .AND. X*Y >Z .OR. X+Y >Z
Evaluate arithmetic expressions first.
Expression: .NOT. FLAG .AND. 15.0 >10.0 .OR. 8.0>10.0
Evaluate relational expressions next.
Expression: .NOT. FLAG .AND. .TRUE. .OR. .FALSE.
Evaluate logical expressions. Start with .NOT..
Expression: .TRUE. .AND. .TRUE. .OR. .FALSE.
Evaluate logical .AND. next.
Expression: .TRUE. .OR. .FALSE.
Evaluate .OR. next
Result: .TRUE.
Example 2: When is the value of the following expression .TRUE.? Assume K
and L are integers.
K / L * L .EQ. K
Solution: If K is divisible by L, the value of the expression is .TRUE.. Otherwise,
the value will be .FALSE..
Example 3: Given that X has a value of 3.0, Y has a value of 5.0, Z has a value
of 10.0, and FLAG is a logical variable with the value .FALSE., find the value of
each of the following expressions:
.NOT. FLAG .OR. FLAG
X > Y - Z / 2.0
X*Z==. 20.0 .OR. FLAG .AND. .NOT. Z== 5.0
X >Y .AND. X >Z .OR. X < Y .AND. X < Z
Z*10 .NE. Y*30 .AND. X < Y .AND. FLAG
.NOT. FLAG .AND. FLAG
.NOT. .NOT. FLAG

Solution:

25
Expression Value
.NOT. FLAG .OR. FLAG .TRUE.
X >Y - Z / 2.0 .TRUE.
X*Z == 20.0 .OR. FLAG .AND. .NOT. Z == 5.0 .FALSE.
X >Y .AND. X >Z .OR. X < Y .AND. X < Z .TRUE.
Z*10 /= Y*30 .AND. X < Y .AND. FLAG .FALSE.
.NOT. FLAG .AND. FLAG .FALSE.
.NOT. .NOT. FLAG .FALSE.

2.6 Assignment Statement


The assignment statement in FORTRAN assigns a value to a variable. The
general form of the FORTRAN assignment statement is:
variable = expression
where expression must have a value of the same type as the variable with one
exception: integer values can be assigned to real variables and real values can be
assigned to integer variables. In assigning a real value to an integer variable, the
decimal part is truncated before the value is stored in the variable. In the case of
an integer value being assigned to a real variable, the integer value is converted
to a real value before it is stored in the variable. The FORTRAN assignment
statement is not a mathematical equation. Therefore, it is possible to write
assignment statements such as:
X = 1.0
X = X + 1.0
where the first statement assigns the value 1.0 to the variable X. The second
statement evaluates the expression X + 1.0 which will be 2.0 and then assigns the
result to the variable X. It should be clear that the old value of X (i.e 1.0) is
changed to the new value (i.e. 2.0).
Example 1: Write FORTRAN assignment statements to store the real number
3.25 into the variable X1 and 7.0 into the variable Y1.
Solution:
X1 = 3.25
Y1 = 7.0

26
Example 2:
Write a FORTRAN assignment statement to store in X1 the value stored in Y1.
Solution:
X1 = Y1
Example 3: Write a FORTRAN assignment statement to increment X1 by 1.
Solution:
X1 = X1 + 1.0
Example 4: Write a FORTRAN assignment statement to add to X1 the value of
Y1.
Solution:
X1 = X1 + Y1
Example 5: Write a FORTRAN assignment statement to store in X1 the contents
of X1 times the contents of Y1.
Solution:
X1 = X1 * Y1
Example 6: Assume that the coefficients of a quadratic equation are given as A,
B, and C. Write FORTRAN assignment statements to find the two roots, ROOT1
and ROOT2, of the quadratic equation.
Solution:
ROOT1 = SQRT (-B + (B ** 2.0 - 4.0 * A * C) / (2.0 * A)
ROOT2 = SQRT (-B - (B ** 2.0 - 4.0 * A * C) / (2.0 * A)

2.7 Simple Input Statement


To read an input value from the terminal into a variable, we must use an input
statement. The general form of the unformatted READ statement has the
following forms:
READ (*,*) list of variables separated by commas
It can be written in another form:
READ*, list of variables separated by commas
The first form starts with READ (*,*) followed by a list of variable names,
separated by commas. The computer will read values from the keyboard
successively and puts the value into the variables.

27
The following points must be noted while using the unformatted READ
statement:
• Each read statement starts reading from a new line.
• If the input data is not enough in the current line, reading continues in the
next line.
• The data values can be separated by blanks or comma.
• The data values must agree in type with the variables.
• Integer values can be read into real variables but real values must not be
read into integer variables.
• Extra data on an input line is ignored.

2.7.1 Examples
Example 1: Assume the following declaration:
INTEGER:: NUM, M1, K, L1, L2, L3, K1, K2
REAL :: TOT, X1, YY, S, ST, A, X, Y, Z
The following table gives examples of READ statements:
Statement Input Line Effect
READ(*,*) NUM,TOT 9 5.08 NUM = 9
TOT = 5.08
READ(*,*) X1, YY 325 27 X1 = 325.0
YY = 27.0
READ(*,*) M1 20.0 ERROR MESSAGE. DATA
TYPE MISMATCH
READ(*,*) K, S 18,0.35E-2 K = 18 S = 0.35E-2

READ(*,*) ST -23.4 ST = -23.4


READ(*,*) L1,L2, L3 7 6 5 L1 = 7
L2 = 6
L3 = 5
READ(*,*) A, A 1.0, 2.0 A = 2.0
READ(*,*) K1 5 8 K1 = 5
READ(*,*) K2 20 9 K2 = 20
READ(*,*) X, Y, Z 5 8 X = 5.0
20 9 Y = 8.0
Z = 20.0
Example 2: Assume the following declaration:
CHARACTER(LEN=9):: NAME, STR1*5, STR2*3
LOGICAL ::P1, P2

28
The following table gives examples of READ statements:

Statement Input Line Effect


READ(*,*) NAME 'AHMED ALI' NAME = 'AHMED ALI'
READ(*,*) STR1, STR2 'ALI' 'CLASS' STR1 = 'ALI '
STR2 = 'CLA'
READ(*,*) P1, P2 T F P1 = .TRUE.
P2 = .FALSE.

Example 3: Assume the following declaration:


CHARACTER(LEN=5) :: Name
REAL :: height, length
INTEGER :: count, MaxLength
READ(*,*) Name, height, count, length, MaxLength

The input data may look like the following:


"Smith" 100.0 25 123.579 10000
Note that all input data are on the same line and separated with spaces. After
reading in this line, the contents of the variables are
Name "Smith"
height 100.0
count 25
length 123.579
MaxLength 100000

• The execution of a READ always starts searching for input values with a
new input line.
Example 4:
INTEGER :: I, J, K, L, M, N
READ(*,*) I, J
READ(*,*) K, L, M
READ(*,*) N

If the above READ statements are used to read the following input lines,
100 200
300 400 500
600

then I, J, K, L, M and N will receive 100, 200, 300, 400, 500 and 600,
respectively.

29
• Consequently, if the number of input values is larger than the number of
variables in a READ statement, the extra values will be ignored. Consider the
following:
Example 5:
INTEGER :: I, J, K, L, M, N
READ(*,*) I, J, K
READ(*,*) L, M, N

If the input lines are


100 200 300 400
500 600 700 800
900

Variables I, J and K receive 100, 200 and 300, respectively. the


second READ starts with a new line, L, M and N receive 500, 600 and 700,
respectively.
• A limited type conversion is possible in a READ statement. If the input value
is an integer and the corresponding variable is of REAL type, the input integer
will be converted to a real number.
But, if the input value is a real number and the corresponding variable is
of INTEGER type, an error will occur.
• The length of the input string and the length of the corresponding
CHARACTER variable do not have to be equal. If they are not equal,
truncation or padding with spaces .
• Finally, a READ without a list of variables simply skips a line of input.
Consider the following:
INTEGER :: P, Q, R, S
READ(*,*) P, Q
READ(*,*)
READ(*,*) R, S

If the input lines are


100 200 300
400 500 600
700 800 900

30
The first READ reads 100 and 200 into P and Q and 300 is lost. The
second READ starts with a new input line, which is the second one. It does not
read in anything. The third READ starts with the third line and reads 700 and
800 into R and S. As a result, the three input values (i.e., 400, 500 and 600) are
all lost. The third value on the third line, 900, is also lost.

2.8 Simple Output Statement


The WRITE output statement is used to print the values of variables expressions
or constants. The general form of the unformatted WRITE statement has the
following forms:
WRITE (*,*) list of variables separated by commas
It can be written in another form:
PRINT*, list of variables separated by commas
The first form starts with WRITE(*,*), followed by a list of arithmetic
expressions or character strings, separated by commas. The computer will
evaluate the arithmetic expressions and displays the results.
The following subsection presents some examples on WRITE statement.
2.8.1 Examples
Example 1: In the table below, examples of the PRINT statement are given
assuming the following initializations:
LOGICAL:: FLAG
INTEGER ::K, L
REAL :: S1, S2
FLAG = .TRUE.
K = 3
L = 20
S1 = 35.0
S2 = S1 - K - L

Statement Output Comments


WRITE(*,*) K, S1 3 35.0000000 Blanks depends the type of
computer
WRITE(*,*) L+S2, W 32.0000000 ??????? for undefined
???????
WRITE(*,*) L, FLAG 20 T
WRITE(*,*) L / K * K 18

31
WRITE(*,*) L / K * K * 1.0 18.0000000
WRITE(*,*) L * 1.0 / K * K 20.0000000 May be 19.9999994
(accuracy)
WRITE(*,*) 5,6+7, L, 2, K+3 5 13 20 2 6 Constants and expressions
WRITE(*,*) 'K= ',K,' L IS ',L K= 3 L IS 20 Characters may be printed
WRITE(*,*) 'THIS TESTS' THIS TESTS
WRITE(*,*) FLAG, .FALSE. T F Logical values either T or F
WRITE(*,*) Prints an empty line

Example 2: In the table below, more examples of the PRINT statement are given
assuming the following initializations:
CHARACTER(10):: LSTNAM
CHARACTER :: CLASS*5, MAJOR*4
LSTNAM = 'AL-FORTRAN'
CLASS = 'BATAL'
MAJOR = 'ANY1'

Statement Output Comments


WRITE(*,*) CLASS, MAJOR BATALANY1 No blanks in between
WRITE(*,*) LSTNAM, ' ',MAJOR AL-FORTRAN ANY1 Explicit blank as it is

The following points must be noted while using the WRITE statement:
• Each WRITE statement starts printing on a new line.
• If the spaces in the line are not enough to hold the whole output, printing
continues on the next line.
• A variable that does not have a value will produce question marks if it is
printed.
Example 3: The following example displays the values of four variables on
screen:

INTEGER :: Factor, N
REAL :: Multiple, tolerance
WRITE(*,*) Factor, N, Multiple, tolerance
Example 4: The following example displays the string content of Title,
followed by the result of (Height + Length) * Area.
CHARACTER(LEN=10) :: Title
REAL :: Height, Length, Area
WRITE(*,*) Title, (Height + Length) * Area
There are some useful rules:

32
Each WRITE starts with a new line.
Consequently, the second form in which the WRITE does not have a list of
expressions just displays a blank line.
INTEGER :: Target
REAL :: Angle, Distance
CHARACTER(LEN=*), PARAMETER :: Time = "The time to hit target " &
IS = " is " &
UNIT = " sec."

Target = 10
Angle = 20.0
Distance = 1350.0
WRITE(*,*) 'Angle = ', Angle
WRITE(*,*) 'Distance = ', Distance
WRITE(*,*)
WRITE(*,*) Time, Target, IS, Angle * Distance, UNIT
This example may produce the following result:
Angle = 20.0
Distance = 1350.0
The time to hit target 10 is 27000sec.
The blank line is generated by the third WRITE.
The above example uses assumed length specifier (i.e., LEN=*)
and continuation lines (i.e., symbol &).
If there are too many results that cannot be fit into a single line, the computer will
display remaining results on the second, the third line and so on.

2.9 A Complete Program


Computing Means
Given three real numbers, its arithmetic mean (average), geometric mean and
harmonic mean are defined as follows:

33
Write a program to compute and display the means of three REAL variables
initialized with positive real values.

Solution
! -------------------------------------------------------
! Computes arithmetic, geometric and harmonic means
! -------------------------------------------------------

PROGRAM ComputeMeans
IMPLICIT NONE

REAL :: X = 1.0, Y = 2.0, Z = 3.0


REAL :: ArithMean, GeoMean, HarmMean

WRITE(*,*) 'Data items: ', X, Y, Z


WRITE(*,*)

ArithMean = (X + Y + Z)/3.0
GeoMean = (X * Y * Z)**(1.0/3.0)
HarmMean = 3.0/(1.0/X + 1.0/Y + 1.0/Z)

WRITE(*,*) 'Arithmetic mean = ', ArithMean


WRITE(*,*) 'Geometric mean = ', GeoMean
WRITE(*,*) 'Harmonic Mean = ', HarmMean

END PROGRAM ComputeMeans

Program Output
Data items: 1., 2., 3.

Arithmetic mean = 2.
Geometric mean = 1.81712067
Harmonic Mean = 1.63636363

34
2.10 Exercises
1. Evaluate the following arithmetic expressions:
1. 4 ** 2 / 3
2. ( ( 2 + 6 ) / 2 + 3.0 /6.0 *4 ) * ( 2 / 4 )
3. 10 ** 2 ** 3
4. 10 / 4 /4 + ( 2 - 10 / 2.0 )

2. Indicate if the statements below are valid FORTRAN statements or not:


1. Y + X = K
2. AB = A * B
3. PRINT*, 1.0, '+', 2.0, '=', 1.0 + 2.0
4. X = Y ** -3
5. X12345 = 8.0
6. X = Y = 5.0
7. P = ( Q + R ) * ( - ( -8 ) )
8. X3X = 8.0
9. READ(*,*) R+A
10. READ(*,*) NUM,NUM

3. Write a program which declares variables to hold the following


data:
(a) an integer set to zero.
(b) an integer set to minus one.
(c) 64.0
(d) -1.56x1012 (this should be written as -1.56E12)
Check the program by writing out variables to the screen.

4. What will be printed by the following FORTRAN programs ?


i. INTEGER:: I, J, K
I = 300
J = 500
K = J/I
WRITE(*,*) K
END
ii. INTEGER:: ONE,TWO,THREE,FOUR,FIVE
ONE = 1
TWO = 2
THREE = 3
FOUR = 4
FIVE = THREE + FOUR ** ( ONE / TWO )

35
WRITE(*,*) FIVE
END

iii. INTEGER:: I, J, K, L
READ(*,*)I, J
READ(*,*) K, I
WRITE(*,*) I, J, K, L
END
Assume the input for the program is:
4 5 6
7 8 9

iv. REAL:: X
X = 1.2
X = X + 1.0
X = X + 1.0
X = X + 1.0
WRITE(*,*) X , X, X, X
END

5. What is the value of each of the following expressions? Use the following
values if needed:
REAL:: A, B
INTEGER:: K, J
A = 2.0
K = -2
B = 3.5
J = 1
1. 6*J/K*4
2. 9+K/5*A/2
3. A/(B+K)/J
4. 3 ** J ** A ** 1 + K / J
5. -2 / 4 * 4 ** 2
6. -2 / 4.0 * 2 ** 2 + 2 * 4.0 ** 2
7. 3 ** 2.0 * ( 3.0 - 1 ) + 2.0 * 1 * 3.0
8. 5 ** 3 / 2 ** 5 / 2
9. ( 5 / 2 ) ** 1.0 ** 2

6. Convert the following FORTRAN assignment statements into an algebraic


form:
1. W = ( X / Y / Z * T ) ** 3 + 1 + 1.674E-24 * C

36
2. Q = 1012.0 * P ** 0.5 * (1.0 - P / 100.0 )
3. K = A * B / C - 2

7. Which of the following are valid FORTRAN variable names?


CS101GRADE AH/Q PRICE
+RATE 2THIRD NUMB_12
IDNUMB BOOK NEW NUMBER-2

8. Which of the following are invalid names in Fortran 90 and why?


abignumber thedate A_HUGE_NUMBER
Time.minutes 10times Program
1066 X HELP!
f[t] no way another-number

9. Indicate the following statements as either TRUE or FALSE:


1. A REAL statement is an executable statement.
2. The statement INTEGER X,Y,Z implies that XYZ is an integer variable.
3. If J, K, and L are integers, then the FORTRAN expressions (J + K) / L and
(J / L) +(K / L) are equivalent.
4. The INTEGER statement can appear any where in the program.
5. WRITE(*,*) X=5 is a valid FORTRAN statement.

10. Write a FORTRAN program which reads the radius of a sphere and calculates
the surface area and the volume of the sphere. Your program should print the
radius, surface area and the volume:
4
Surface area = 4  r2 & Volume =  r3
3
11. Convert the following mathematical expressions / assignments to FORTRAN
expressions / assignments. (Do not use extra parentheses)
𝑦
1. 2𝑥 + 𝐴 = 𝜋𝑟 2
2

𝑎+𝑏
2. √
𝑎−𝑏
3
𝑟3 𝑎𝑐 4
3. −
3 2𝑏
1
4. 1 1 1
+ +
𝑟1 𝑟2 𝑟3

37
𝑥𝑦
5. 𝑎=𝑏+ +2
𝑐+𝑑

6. 2𝑎 + 𝑐 −6

12. The input data to a certain program is more than what is required. The data
is as follows:
4 5 12 10
6 1 8 13 19
3 2 9 0 7 18 20
Write a FORTRAN program to read enough data (i.e. using the minimum
number of variables in the READ statement) to print the following output:
4 5
1 8
9 0
(your program should have READ and PRINT statements only)

13. i) The output of the program below is as follows:


8
Fill in the spaces to get the output shown above
INTEGER:: K, M, N
K = -----
M = 2
N = 3
WRITE(*,*) M**N**M**K
END
ii) The output of the program below is as follows:
1 4
7 8 10
Fill in the spaces to get the output shown above
INTEGER:: K1, K2, K3, K4, K5
READ(*,*) -------
READ(*,*) -------
READ(*,*) -------
WRITE(*,*) K1, K2
WRITE(*,*) K3,K4,K5
END
Assume the input for the program is:
1 2 3
4 5 6
7 8
10 11 12

38
14. Determine whether the following conditions are TRUE or FALSE. Assume
A = 3.5, B = -4.1, I = -4, J = 9, FLAG = .TRUE. when needed:
1. (3.0/2<1.5).AND.(4/2 >1)
2. .FALSE..AND..TRUE..OR..NOT.(.FALSE..AND..TRUE.)
3. .NOT..FALSE..AND..TRUE.
4. .NOT..FALSE..OR..TRUE..AND.3/2==1.0
5. .NOT.5**2 == 5*2.AND.0> 5.OR.5*2+2> 0

15. What are the logical values of the following expressions?


1. 15 > 23
2. (12+3) <= 15
3. (2>1) .AND. (3<4)
4. ((3>2) .AND. (1+2)<3) .OR. (4<=3)
5. .AND. (1+2)<3) .EQV. (4<=3)

16. Determine whether the following conditions are TRUE or FALSE.


a) Let LOGICAL variables Something and Another have values. TRUE.
and. FALSE., respectively.
i) .NOT. Something .AND. Another
ii) .NOT. (Something .AND. Another)
b) Let LOGICAL variables a, b and c have values .TRUE., .TRUE.
and .FALSE., respectively.
.NOT. a .OR. .NOT. b .AND. c
c) Let INTEGER variable n have a value of 4:
n**2 + 1 > 10 .AND. .NOT. n < 3
d) Let INTEGER variables m, n, x and y have values 3, 5, 4 and 2,
respectively:
.NOT. (m > n .AND. x < y) .NEQV. (m <= n .AND. x >= y)

39
3. Control statements
Fortran 90 has three main types of control construct:
• IF statement
• S E L E C T CASE statement
• DO Loops

3. 1 SELECTION CONSTRUCTS ) IF statement)


In FORTRAN, the IF statement is used to represent selection constructs, which
actually has several forms as:

3.1.1 Form 1: IF-THEN-ELSE-END IF


The most general form of the IF-THEN-ELSE-END IF statement is the following:
IF (logical-expression) THEN
statements-1
ELSE
statements-2
END IF
where statements-1 and statements-2 are sequences of executable statements,
and logical-expression is a logical expression. The execution of this IF-THEN-
ELSE-END IF statement goes as follows:

• the logical-expression is evaluated, yielding a logical value


• if the result is .TRUE., the statements in statements-1 are executed
• if the result is .FALSE., the statements in statements-2 are executed
• after finish executing statements in statements-1 or statements-2, the
statement following END IF is executed.

Examples on the IF-THEN-ELSE-END IF

Example 1: The following code first reads in an integer


into INTEGER variable Number. Then, if Number can be divided evenly by 2
(i.e., Number is a multiple of 2), the WRITE(*,*) between IF and ELSE is
executed and shows that the number is even; otherwise,
the WRITE(*,*) between ELSE and END IF is executed and shows that the

40
number is odd. Function MOD(x,y) computes the remainder of x divided by y. This
is the the remainder (or modulo) function
INTEGER :: Number

READ(*,*) Number
IF (MOD(Number, 2) == 0) THEN
WRITE(*,*) Number, ' is even'
ELSE
WRITE(*,*) Number, ' is odd'
END IF

Example 2: The following program segment reads in two integer values


into a and b and finds the smaller one into Smaller. Note that
the WRITE(*,*) has also been broken into two lines.
INTEGER :: a, b, Smaller

READ(*,*) a, b
IF (a <= b) THEN
Smaller = a
ELSE
Smaller = b
END IF
WRITE(*,*) 'The smaller of ', a, ' and ', &
b, ' is ', Smaller

Program input and output


if the input line is as follows:
347 670
The output will be as follows:
The smaller of 347 and 670 is Smaller is 347

Example 3: Write a FORTRAN program that reads an integer number and finds out
if the number is even or odd. The program should print a proper message.
Solution:
PROGRAM even_odd
IMPLICIT NONE

INTEGER :: K
READ(*,*) K
WRITE (*,*) 'INPUT: ', K
IF(K / 2 * 2 .EQ. K) THEN
41
WRITE (*,*) 'EVEN'
ELSE
WRITE (*,*) 'ODD'

ENDIF
END PROGRAM even_odd

Program input and output

if the input is as follows:


79
The output will be as follows:
INPUT: 79
ODD

3.1.2 Form 2: IF-THEN-END IF

The IF-THEN-END IF form is a simplification of the general IF-THEN-ELSE-


END IF form with the ELSE part omitted:

IF (logical-expression) THEN
statements
END IF

where statements is a sequence of executable statements, and logical-expression is a


logical expression. The execution of this IF-THEN-ELSE-END IF statement goes
as follows:

• the logical-expression is evaluated, yielding a logical value


• if the result is .TRUE., the statements in statements are executed, followed
by the statement following the IF-THEN-END IF statement.
• if the result is .FALSE., the statement following the IF-THEN-END IF is
executed. In other words, if logical-expression is .FALSE., there is no action
taken.

Examples on the IF-THEN-END IF


Example 1: The following program segment computes the absolute value of X and
saves the result into variable Absolute_X. Recall that the absolute value

42
of x is x if x is non-negative; otherwise, the absolute value is -x. For example, the
absolute value of 5 is 5 and the absolute value of -4 is 4=-(-4). Also note that
the WRITE(*,*) statement has been intentionally broken into two lines with the
continuation line symbol &. The trick is that the value of X is first saved
to Absolute_X whose value is changed later only if the value of X is less than zero.
REAL :: X, Absolute_X

X = .....
Absolute_X = X
IF (X < 0.0) THEN
Absolute_X = -X
END IF
WRITE(*,*) 'The absolute value of ', x, &
' is ', Absolute_X

Example 2: The following program segment reads in two integer values into a
and b and finds the smaller one into Smaller.
INTEGER :: a, b, Smaller

READ(*,*) a, b
Smaller = a
IF (a > b) THEN
Smaller = b
END IF
WRITE (*,*) 'The smaller of ', a, ' and ', &
b, ' is ', Smaller
In many cases, it is required to do something when certain condition is satisfied;
otherwise, do nothing. This is exactly what we need the form of IF-THEN-END
IF. In the following, an INTEGER variable Counter is used for counting
something. When its value is a multiple of 10, a blank line is displayed.
Example 3:
INTEGER :: Counter

IF (MOD(Counter, 10) == 0) THEN


WRITE(*,*)
END IF

Example 4: Write a FORTRAN program that reads a grade. If the grade is not zero,
the program must add 2 points to the grade. Then, the new grade should be printed.
Solution:

PROGRAM grade
43
IMPLICIT NONE

REAL:: GRADE
READ(*,*) GRADE
WRITE (*,*) 'ORIGINAL GRADE IS', GRADE
IF (GRADE >0) THEN
GRADE = GRADE + 2.0
WRITE (*,*) 'SCALED GRADE IS ', GRADE
ENDIF
END PROGRAM grade

Program input and output

if the input line is as follows:


7.5
The output is as follows:
ORIGINAL GRADE IS 7.5000000
SCALED GRADE IS 9.5000000

if the input line is as follows:


0.0
The output is as follows:
ORIGINAL GRADE IS 0.0000000

3.1.3 Form 3: Logical IF


The logical IF is the simplest form. It has the following form:

IF (logical-expression) one-statement

where one-statement is a executable statement which is not another IF, and logical-
expression is a logical expression. The execution of this logical IF statement goes as
follows:

• the logical-expression is evaluated, yielding a logical value


• if the result is .TRUE., the statement in one-statement is executed, followed
by the statement following the logical IF statement.
• if the result is .FALSE., the statement following the logical IF is executed.
In other words, when logical-expression is .FALSE., there is no action
taken.

44
Examples on the Logical IF
• In many cases, it is required to do something when certain condition is satisfied;
otherwise, do nothing. This is exactly what we need the form of IF-THEN-END
IF.
Example 1: In the following, an INTEGER variable Counter is used for counting
something. When its value is a multiple of 10, a blank line is displayed.

INTEGER :: Counter

IF (MOD(Counter, 10) == 0) WRITE(*,*)

Example 2: Use simple IF constructs to write a FORTRAN program that reads a


student ID and his GPA out of 4.0. The program should print a message according
to the following:
Condition Message
GPA  3.5 EXCELLENT
3.5 > GPA  3.0 VERY GOOD
3.0 > GPA  2.5 GOOD
2.5 > GPA  2.0 FAIR
GPA < 2.0 POOR
Solution:
PROGRAM student_ID
IMPLICIT NONE

INTEGER:: ID
REAL:: GPA
CHARACTER(LEN=10):: STATE
READ(*,*) ID, GPA
WRITE(*,*) 'INPUT: ', ID, GPA
IF (GPA >= 3.5) STATE = 'EXCELLENT'
IF (GPA >= 3.0 .AND. GPA<3.5) STATE ='VERY GOOD'
IF (GPA >= 2.5 .AND. GPA < 3.0) STATE = 'GOOD'
IF (GPA>= 2.0 .AND. GPA < 2.5) STATE = 'FAIR'
IF (GPA < 2.0) STATE = 'POOR'
WRITE(*,*) ID,' ', STATE
END PROGRAM student_ID
Example 2: Write a FORTRAN program that reads three integer numbers and
finds and prints the maximum. Use simple IF constructs.
Solution:

45
PROGRAM the_maximum
IMPLICIT NONE

INTEGER:: X1, X2, X3, MAXIM


READ(*,*) X1, X2, X3
WRITE(*,*) 'THE NUMBERS ARE ', X1, X2, X3
MAXIM = X1
IF (X2 >MAXIM) MAXIM = X2
IF (X3 >MAXIM) MAXIM = X3
WRITE(*,*) 'THE MAXIMUM OF THE THREE NUMBERS IS ', MAXIM
END PROGRAM the_maximum

3.1.4 Form 4: IF-THEN-ELSE IF-END IF

The general form of this construct is as follows:


IF (logical-expression-1) THEN
statements-1
ELSE IF (logical-expression-2) THEN
statements-2
ELSE IF (logical-expression-3) THEN
statement-3
ELSE IF (.....) THEN
...........
ELSE
statements-ELSE
END IF

Fortran evaluates logical-expression-1 and if the result is .TRUE., statements-1 is


executed followed by the statement after END IF. If logical-expression-
1 is .FALSE., Fortran evaluates logical-expression-2 and executes statements-2 and
so on. In general, if logical-expression-n is .TRUE., statements-n is executed
followed by the statement after END IF; otherwise, Fortran continues to evaluate
the next logical expression.
If all logical expressions are .FALSE. and if ELSE is there, Fortran executes
the statements-ELSE; otherwise, Fortran executes the statement after the END IF.

Examples on the IF-THEN-ELSE IF-END IF


Example 1: Suppose we need a program segment to read a number x and display its
sign. More precisely, if x is positive, a + is displayed; if x is negative, a - is
displayed; otherwise, a 0 is displayed. Here is a possible solution using
IF-THEN-ELSE IF-END IF:
IF (x > 0) THEN
WRITE(*,*) '+'
ELSE IF (x == 0) THEN
46
WRITE(*,*) '0'
ELSE
WRITE(*,*) '-'
END IF

Example 2: Given a x, we want to display the value of -x if x < 0, the value


of x*x if x is in the range of 0 and 1 inclusive, and the value of 2*x if x is greater
than 1. The following is a possible solution:
IF (x < 0) THEN
WRITE(*,*) -x
ELSE IF (x <= 1) THEN
WRITE(*,*) x*x
ELSE
WRITE(*,*) 2*x
END IF

Programming Example: Quadratic Equation Solver


Given a quadratic equation as follows:

if b*b-4*a*c is non-negative, the roots of the equation can be solved with the
following formulae:

Write a program to read in the coefficients a, b and c, and compute and display the
roots. If the discriminant b*b - 4*a*c is negative, the equation has complex root.
Thus, this program should solve the equation if the discriminant is non-negative and
show a message otherwise.
Solution
! ---------------------------------------------------
! Solve Ax^2 + Bx + C = 0 given B*B-4*A*C >= 0
! Now, we are able to detect complex roots.
! ---------------------------------------------------

PROGRAM QuadraticEquation
IMPLICIT NONE

REAL :: a, b, c
REAL :: d
REAL :: root1, root2

! read in the coefficients a, b and c

47
READ(*,*) a, b, c
WRITE(*,*) 'a = ', a
WRITE(*,*) 'b = ', b
WRITE(*,*) 'c = ', c
WRITE(*,*)

! compute the square root of discriminant d

d = b*b - 4.0*a*c
IF (d >= 0.0) THEN ! is it solvable?
d = SQRT(d)
root1 = (-b + d)/(2.0*a) ! first root
root2 = (-b - d)/(2.0*a) ! second root
WRITE(*,*) 'Roots are ', root1, ' and ', root2
ELSE ! complex roots
WRITE(*,*) 'There is no real roots!'
WRITE(*,*) 'Discriminant = ', d
END IF

END PROGRAM QuadraticEquation

Program Input and Output


If the input to the program consists of 1.0, 5.0 and 2.0, we have the following output.
1.0 5.0 2.0

a = 1.
b = 5.
c = 2.

Roots are -0.438447237 and -4.561553

3.1.5 Nested IF-THEN-ELSE-END IF


You can use as many IF-THEN-ELSE-END IF statements in the THEN part and
the ELSE part as you want. The following is an example:
IF (logical-expression) THEN
statements
IF (logical-expression) THEN
statements
ELSE
statements
END IF
statements
ELSE
statements
IF (logical-expression) THEN
statements
END IF
statements
END IF

48
Examples
• Suppose we need a program segment to read a number x and display its sign. More
precisely, if x is positive, a + is displayed; if x is negative, a - is displayed;
otherwise, a 0 is displayed. With an IF-THEN-ELSE-END IF statement, we have
a two-way decision (i.e., true or false).
IF (x > 0) THEN
WRITE(*,*) '+'
ELSE
IF (x < 0) THEN
WRITE(*,*) '-'
ELSE
WRITE(*,*) '0'
END IF
END IF
• Given a x, we want to display the value of -x if x < 0, the value of x*x if x is in
the range of 0 and 1 inclusive, and the value of 2*x if x is greater than 1.
Converting to using IF, we have the following:
IF (x < 0) THEN
WRITE(*,*) -x
ELSE
IF (x <= 1) THEN
WRITE(*,*) x*x
ELSE
WRITE(*,*) 2*x
END IF
END IF

3.2 SELECT CASE Statement


Fortran has one more selective execution statement, SELECT CASE, and could be
very handy if it is used properly. The SELECT CASE statement is also usually
referred to as the CASE statement. The following is its syntactic form:
SELECT CASE (selector)
CASE (label-list-1)
statements-1
CASE (label-list-2)
statements-2
CASE (label-list-3)
statements-3
.............
CASE (label-list-n)
statements-n
CASE DEFAULT
statements-DEFAULT
END SELECT

49
where statements-1, statements-2, statements-3, ..., statements-n and statements-
DEFAULT are sequences of executable statements, including the SELECT
CASE statement itself. The label lists label-list-1, label-list-2, label-list-3, ...,
and label-list-n are called case labels.
A label-list is a list of labels, separated by commas. Each label must be one of the
following forms. In fact, three of these four are identical to an extent specifier for
substrings:
value
value-1 : value-2
value-1 :
: value-2

where value, value-1 and value-2 are constants. The type of these constants must
be identical to that of the selector.
• The first form has only one value
• The second form means all values in the range of value-1 and value-2. In
this form, value-1 must be less than value-2.
• The third form means all values that are greater than or equal to value-1
• The fourth form means all values that are less than or equal to value-2

The rule of executing the SELECT CASE statement goes as follows:

• The selector expression is evaluated


• If the result is in label-list-i, then the sequence of statements in statements-
i are executed, followed by the statement following END SELECT
• If the result is not in any one of the label lists, there are two possibilities:
o if CASE DEFAULT is there, then the sequence of statements
in statements-DEFAULT are executed, followed by the statement
following END SELECT
o if there is no CASE DEFAULT is not there, the statement
following END SELECT is executed.
There are some notes for writing good Fortran programs:
• The constants listed in label lists must be unique
50
• CASE DEFAULT is optional. But with a CASE DEFAULT, you are
guaranteed that whatever the selector value, one of the labels will be used. I
strongly suggest to add a CASE DEFAULT in every SELECT
CASE statement.
• The place for CASE DEFAULT can be anywhere within a SELECT
CASE statement; however, put it at the end would be more natural.
Examples
Example 1:
• The following uses Class to execute a selection. If Class is 1, Freshman is
displayed; if Class is 2, Sophomore is displayed; if Class is 3, Junior is
displayed; if Class is 4, Senior is displayed; and if Class is none of the
above, Hmmmm, I don't know is displayed. After displaying one of the
above, Done is displayed.
INTEGER :: Class

SELECT CASE (Class)


CASE (1)
WRITE(*,*) 'Freshman'
CASE (2)
WRITE(*,*) 'Sophomore'
CASE (3)
WRITE(*,*) 'Junior'
CASE (4)
WRITE(*,*) 'Senior'
CASE DEFAULT
WRITE(*,*) "Hmmmm, I don't know"
END SELECT
WRITE(*,*) 'Done'

Example 2:

• In the following, the value of CHARACTER variable Title is used as a selector.


If its value is "DrMD" (resp., "PhD", "MS" and "BS"),
then INTEGER variables DrMD (resp., PhD, MS and BS) is increased by 1.
Otherwise, Others is increased.

CHARACTER(LEN=4) :: Title
INTEGER :: DrMD = 0, PhD = 0, MS = 0, BS = 0, Others = 0

SELECT CASE (Title)


CASE ("DrMD")

51
DrMD = DrMD + 1
CASE ("PhD")
PhD = PhD + 1
CASE ("MS")
MS = MS + 1
CASE ("BS")
BS = BS + 1
CASE DEFAULT
Others = Others + 1
END SELECT

Example 3:
• The following program uses the value of Number to determine the value
of Range.
INTEGER :: Number, Range

SELECT CASE (Number)


CASE ( : -10, 10 : )
Range = 1
CASE (-5:-3, 6:9)
Range = 2
CASE (-2:2)
Range = 3
CASE (3, 5)
Range = 4
CASE (4)
Range = 5
CASE DEFAULT
Range = 6
END SELECT

Here is the result:

Number Range Why?

<= -10 1 CASE ( : -10, 10 : )


-9, -8, -7, -6 6 CASE DEFAULT
-5, -4, -3 2 CASE (-5:-3, 6:9)
-2, -1, 0, 1, 2 3 CASE (-2:2)
3 4 CASE (3, 5)
4 5 CASE (4)
5 4 CASE (3, 5)
6, 7, 8, 9 2 CASE (-5:-3, 6:9)
>= 10 1 CASE ( : -10, 10 : )

52
Programming Example: Computing Letter Grade
At the end of a quarter, the average of three marks must be computed. Then, this
average is rounded and used to determine the corresponding letter grade. The letter
grades are computed as follows:

Range Grade
>= 90 A
< 90 and >= 85 AB
< 85 and >= 80 B
< 80 and >= 75 BC
< 75 and >= 70 C
< 70 and >= 65 CD
< 65 and >= 60 D
< 60 F

Write a program to read three marks, compute its average, round the average and
use it to determine the corresponding letter grade.
Solution
! ----------------------------------------------------------
! This program reads three marks, computes their average
!
! ----------------------------------------------------------

PROGRAM LetterGrade
IMPLICIT NONE

REAL :: Mark1, Mark2, Mark3


REAL :: Average
CHARACTER(LEN=2) :: Grade

READ(*,*) Mark1, Mark2, Mark3


Average = (Mark1 + Mark2 + Mark3) / 3.0

SELECT CASE (NINT(Average)) ! round Average before use


CASE (:59) ! <= 59 -------------> F
Grade = 'F '
CASE (60:64) ! >= 60 and <= 64 ---> D
Grade = 'D '
CASE (65:69) ! >= 65 and <= 69 ---> CD
Grade = 'CD'
CASE (70:74) ! >= 70 and <= 74 ---> C
Grade = 'C '
CASE (75:79) ! >= 75 and <= 79 ---> BC
Grade = 'BC'

53
CASE (80:84) ! >= 80 and <= 84 ---> B
Grade = 'B '
CASE (85:89) ! >= 84 and <= 89 ---> AB
Grade = 'AB'
CASE DEFAULT ! >= 90 -------------> A
Grade = 'A '
END SELECT

WRITE(*,*) 'First Mark : ', Mark1


WRITE(*,*) 'Second Mark : ', Mark2
WRITE(*,*) 'Third Mark : ', Mark3
WRITE(*,*) 'Average : ', Average
WRITE(*,*) 'Letter Grade : ', Grade

END PROGRAM LetterGrade

Program Input and Output


The following output is generated from input 92.0, 85.0 and 83.0. The average is
86.6666641. The result after rounding is 87 and hence the letter grade is an AB.
92.0 85.0 83.0

First Mark : 92.


Second Mark : 85.
Third Mark : 83.
Average : 86.6666641
Letter Grade : AB

3.3 GOTO
The GOTO statement can be used to transfer control to another statement, it
has the form:
GOTO label
The GOTOstatement simply transfers control to the statement, skipping any
state- ments in between. For example:
...
IF( x<10 ) GOTO 10
...
10 STOP

54
3.4 Exercises

1. What will be printed by the following programs? If an error message is


generated, which statement causes the error?
1. INTEGER:: N, M
N = 15
M = 10
IF (M >= N) THEN
M = M + 1
IF (N ==M) THEN
N = N + 5
ELSEIF (N >= 0) THEN
N = N + 10
ENDIF
M = M – 1
ENDIF
M = M - 1
WRITE(*,*) M, N
END

2. REAL:: A,B
INTEGER:: I
READ(*,*) A, I, B
IF (A<3.0) THEN
WRITE(*,*)A+I
IF (B<2.5) THEN
WRITE(*,*)B**I
ENDIF
ELSE
WRITE(*,*) A*B*I
ENDIF
END
Assume the input for the program is:
2.5 2 2.5

3. NTEGER:: A, B, C
READ(*,*) A, B, C
IF (A > B) THEN
IF (B<C) THEN
WRITE(*,*)B
ELSE
WRITE(*,*)C
ENDIF
ELSE
WRITE(*,*)A
ENDIF
WRITE(*,*)A, B, C
END
Assume the input for the program is:
-2 -4 -3

55
4. LOGICAL:: A,B
INTEGER:: K1, K2
K1 = 10
K2 = 12
A = K1<K2
B = .TRUE.
IF (A) B = .FALSE.
WRITE(*,*)A, B
END

2. Consider the following FORTRAN 77 program segment :


IF (A> B .OR. A == B) PRINT*, A
Which one(s) of the following segments is(are) equivalent to the above?
I. IF (A > B) THEN
WRITE(*,*)A
ENDIF
II. IF (A > B .AND. A == B) THEN
WRITE(*,*)A
ENDIF
III. IF (.NOT. (A<B) ) THEN
WRITE(*,*)A
ENDIF
3. What values of X cause the value of A to be changed in the following statement?
IF (X<3.0 .AND. 7.0<X) A = A + 1
4. Give the FORTRAN statements that perform the steps indicated
below :
1. If y is not positive, and 3.5>x>1.5 then print the value of y.
2. If time is greater than 15.0, increment time by 1.0.
3. If dist is less than 50.0 and time is greater than 10.0, increment
time by 2.0. Otherwise, increment time by 2.5.
5. Write a program that reads an integer number N and prints YES if the following
expression is satisfied.
0 < N < 100 and N > 50

6. Consider the following IF statement:


IF (X>= Y) THEN
PRINT*, X
ELSE
WRITE(*,*)Y
ENDIF

In each of the following program segments, fill the spaces by relational or


logical operators such that each of the program segments below gives the same
output as the program segment above.

56
I. IF (X ------ Y) WRITE(*,*)X
IF (X ------ Y) WRITE(*,*)Y

II. IF (X > Y) THEN


WRITE(*,*)X
ELSEIF (X ----- Y) THEN
WRITE(*,*)X
ELSE
WRITE(*,*)Y
ENDIF

III. IF (X ----- Y ----- X ==Y) THEN


WRITE(*,*)X
ELSE
WRITE(*,*)Y
ENDIF

57
3.5. REPETITION (LOOPS)
While writing a program, it may be necessary to execute a statement or a group of
statements repeatedly. Repetition is supported in FORTRAN through two repetition
constructs. A repetition construct is known as a loop.

3.5.1 Counting DO-Loop


One very basic feature of the DO loop repetitive construct is that the number of
iterations (the number of times the loop is executed) is known (computed) before the
loop execution begins. The general form of the counting loop is the following:

DO index = initial, limit, increment


statements
END DO

another form: Block Do Construct With CONTINUE

DO N index = initial, limit, increment


BLOCK OF FORTRAN STATEMENTS
N CONTINUE

The CONTINUE statement indicates the end of the DO loop.

The detailed logic of the DO loop is as follows:


• If the increment is positive, the value of the initial must be less than or equal
to the value of the limit. If the increment is negative, the value of the initial
must be greater than or equal to the value of the limit. Otherwise, the loop will
not be executed. If the values of the initial and the limit are equal, the loop
executes only once.
• In the first iteration, the index of the loop has the value of initial
• Once the END DO statement is reached, the index is increased or decreased
by the increment and the execution of the next iteration starts. Before each
iteration, the index is checked to see if it has reached the limit. If the index reaches
58
the limit, the loop iterations stop. Otherwise, the next iteration begins.
Consider the following example as an illustration of the Counting DO loop :
INTEGER :: Count

DO Count = -1, 5, 2
WRITE(*,*) Count
END DO

Program output
-1
1
3

The following rules apply to DO loops:


• The index of a DO loop must be a variable of either INTEGER or REAL types.
(note you should avoid using REAL numbers).
• The parameters of the loop, namely, initial, limit, and increment can be
expressions of either INTEGER or REAL types. Although it depends on the
nature of the problem being solved, it is recommended that the type of the
parameters match the type of the index.
• The value of the DO loop index cannot be modified inside the loop. Any attempt
to modify the index within the loop will cause an error.
• The increment must not be zero, otherwise an error occurs.
• It is not allowed to branch into a DO loop. Entering the DO loop has to be
through its DO statement. It is possible to branch out of a DO loop before all
the iterations are completed. This type of branching must not be used unless
necessary.
• In the DO loop construct, in the absence of the increment, the default increment
is +1 or +1.0 depending on the type of the index.
The following examples illustrate the ideas explained above:
Consider the following program.
INTEGER, PARAMETER :: Init = 3, Final = 5
INTEGER :: Iteration

DO Iteration = Init, Final


WRITE(*,*) 'Iteration ', Iteration
END DO
59
In the above program, since steps-size (the increment ) is omitted, it is assumed to
be 1. Therefore, the index Iteration receives 3, 4, and 5 in this order.

Some 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 increement. 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, limit and increment. 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
60
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.

3.5.2 Examples on Counting DO-Loop


• In addition to repeatedly processing some data as shown above, the DO-loop
has some other uses as presented in the following examples:
Example 1:
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 then the final
value of Sum is 17 = 3+6+8.
Example 2:
Factorial: A simple variation could be used to compute the factorial of a positive
integer. The factorial of an integer N, written as
N! = N*(N-1)*(N-2)*...*3*2*1.
INTEGER :: Factorial, N, I

Factorial = 1
DO I = 1, N
Factorial = factorial * I
END DO

61
Programming Example: Computing Factorial

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

Program Input and Output

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

62
This program computes the factorial of
a non-negative integer

What is N in N! -->
5

5! = 120

3.5.3 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
READ(*,*) x
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 EXIT Statement.
3.5.4 The EXIT Statment
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.
63
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
Example
• 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
READ(*,*) x
IF (x < 0) EXIT
Sum = Sum + x
END DO

Programming Example: Computing EXP(x)

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


infinite series:

64
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
! ---------------------------------------------------------

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

READ(*,*) X ! read in x
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

65
3.5.5 Nested DO Loops
DO loops can be nested, that is you may have a DO loop inside another DO loop.
However, one must start the inner loop after starting the outer loop and end the inner
loop before ending the outer loop. It is allowed to have as many levels of nesting as
one wishes. The constraint here is that inner loops must finish before outer ones and
the indexes of the nested loops must be different.
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:

Examples on Nested DO loops


Example 1:
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

66
Example 2:
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

Example 3:
Nested DO Loops: Consider the following program.
INTEGER :: M, j
DO M = 1, 2
DO j = 1, 6 , 2
WRITE(*,*) M, J
END DO
END DO

The output of the above program is:


1 1
1 3
1 5
2 1
2 3
2 5

3.5.6 WHILE-loops (Fortran: DO-WHILE-loops)

In many cases, it is convenient to combine the features of the block DO and block
IF constructs into one construct featuring the best of both. The DO WHILE statement
is a conditional loop construct that performs this function.
The block DO WHILE construct conditionally executes a block as many times as
necessary, as long as the tested logical expression included in the DO WHILE
statement continues to be satisfied at every iteration of the loop.

67
The DO WHILE statement has the form:

DO WHILE (logical argument)


statements
END DO

• label is the numeric statement label of a corresponding END DO or


CONTINUE statement which must follow the DO WHILE statement in the
same program unit.
• logical argument is a valid logical expression which is tested at each pass
through the loop.
For instance,
Example 1:
REAL, PARAMETER :: B = 100.
DO WHILE (B >= 5)
WRITE(*,*) ` The VALUE OF B IS =`,B
B=B-10.
END DO

This loop is executed 10 times, with B being decremented by 10. at every iteration
of the loop. The loop finishes when B is less than 5.

Example 2: Invalid DO WHILE Loop (Infinite Loop)


REAL, PARAMETER :: B = 5.
DO WHILE (B >= 0.)
WRITE(*,*) ` The VALUE OF B IS =`,B
B=B+1.
END DO

This loop continues to execute while B ≥ 0. The loop is set up in such a way that this
condition is always satisfied. The initial value of B is 5., and B continues to increase
with every iteration of the loop. Therefore, there is no way to logically terminate the
loop. This construct will not produce an error upon execution, but will tie up the
processor in an infinite loop.

3.5.7 Nested DO WHILE Loops

Just as with DO loops (Section 7.1), it is often necessary to place one or more DO
WHILE loops inside of another DO WHILE loop. This is referred to as "nesting"

68
DO WHILE loops. As stated previously, the nested loop should be completely
contained within the nesting loop.
The following rules apply to nested DO WHILE loops:
• Nested and nesting DO WHILE loops cannot share the same unlabeled END
DO statement.
• Nested and nesting DO WHILE loops can share the same labeled END DO
statement.
• If two or more nested DO WHILE loops share the same labeled END DO
statement, control can be transferred to that statement only from within the
innermost DO WHILE block.

Example 1: Labeled Nested DO WHILE Statements


DO WHILE (A >= 0.)
……….. ! block 1
A= A - 0.5
DO 20 WHILE (A >= 5.)
……….. ! block 2
B= B - 1.5
END DO
END DO

Block 1 is executed if A ≥ 0. If block 1 is executed, block 2 is also executed, provided


B ≥ 5. Both A and B need to decrease at every iteration of the loop if the nested DO
WHILE construct is to eventually terminate.
The WHILE-loops can be built from the IF and the GOTO statements. The IF-
THEN construct is used to perform the test at the beginning of the loop. Consider
an IF statement, which has the following structure :
IF (condition) THEN
block of statements
ENDIF

If the condition is .TRUE., the block of statements is executed once. For the next
iteration, since we need to go to the beginning of the IF statement, we require the
GOTO statement. It has the following general form :
GOTO statement number

A GOTO statement transfers control to the statement that has the given statement
69
number. Using the IF and the GOTO statements, the general form of the WHILE
loop is as follows :
n IF (condition) THEN
block of statements
GOTO n
ENDIF

n is a positive integer constant. It is the label of the IF statement.

The execution of the loop starts if the condition evaluates to a .TRUE. value. Once
the loop iterations begin, the condition must be ultimately changed to a .FALSE.
value, so that the loop stops after a finite number of iterations. Otherwise, the loop
never stops resulting in what is known as the infinite loop. In the following section,
we elaborate more on the WHILE loop.
Example 1: Computation of the Average: Write a FORTRAN program that reads
the grades of 100 students in a course. The program then computes and prints the
average of the grades.
Solution:
PROGRAM the_Average
IMPLICIT NONE
REAL:: X, AVG, SUM
INTEGER:: K
K = 0
SUM = 0.0
25 IF (K<100) THEN
READ(*,*) X
K = K + 1
SUM = SUM + X
GOTO 25
ENDIF
AVG = SUM / K
WRITE(*,*) AVG
END PROGRAM the_Average

Note that the variable K starts at 0. The value of K is incremented after the reading
of a grade. The IF condition presents the loop from reading any new grades once the
100th grade is read. Reading the 100th grade causes K to be incremented to the value
of 100 as well. Therefore, when the condition is checked in the next iteration, it
becomes .FALSE. and the loop stops.

70
In each iteration, the value of the variable GRADE is added to the variable SUM.
After the loop, the average is computed by dividing the variable SUM by the variable
K.

Examples on DO and WHILE Loops


Example 1: Evaluation of Series: Write a FORTRAN program that evaluates the
following series to the 7th term.
∑7𝑖=1 3𝑖
(Summation of base 3 to the powers from 1 to N. Assume N has the value 7)
Solution:
PROGRAM Series
IMPLICIT NONE
INTEGER:: SUM
SUM = 0
DO K = 1, 7
SUM = SUM + 3 ** K
END DO
WRITE(*,*) SUM
END PROGRAM Series

Example 2: Alternating Sequences/ Series: Alternating sequences, or series, are


those which have terms alternating their signs from positive to negative. In this
example, we find the sum of an alternating series. Question: Write a FORTRAN
program that evaluates the following series to the 100th term.
1 - 3 + 5 - 7 + 9 - 11 + 13 - 15 + 17 - 19 + ...
Solution:
It is obvious that the terms differ by 2 and start at the value of 1.

PROGRAM Alternating
IMPLICIT NONE
INTEGER:: SUM, TERM,NTERM
SUM = 0
TERM = 1
DO NTERM = 1, 100
SUM = SUM + (-1) ** (NTERM + 1) * TERM
TERM = TERM + 2
END DO
WRITE(*,*) SUM
END PROGRAM Alternating

Notice the summation statement inside the loop. The expression (-1) ** (NTERM +
71
1) is positive when NTERM equals 1, that is for the first term. Then, it becomes
negative for the second term since NTERM + 1 is 3 and so on.

3.5.8 Implied Loops

Implied loops are only used in READ and PRINT statements. The implied loop is
written in the following manner :
READ(*,*) (list of variables, index = initial, limit, increment)

WRITE(*,*) (list of expressions, index = initial, limit, increment)

As in the case of explicit DO loops, the index must be either an integer or real
expression. The variables in the READ statement can be of any type including array
elements. The expressions in the PRINT statement can be of any type as well. All
the rules that apply to DO loop parameters also apply to implied loop parameters.
Usage of implied loops is given in the following examples:

Example 1: Printing values from 100 to 87: The following segment prints the integer
values from 100 down to 87 in a single line.
WRITE(*,*) (K, K = 100 , 87 , -1)
Output:
100 99 98 97 96 95 94 93 92 91 90 89 88 87
Notice that the increment is -1, which means that the value of K decreases from
100 to 87. In each iteration, the value of K is printed. Since K is the index of the
loop, the value printed here is the value of the index, which varies in each iteration.
Consider the following explicit DO loop version of the implied loop:

DO K = 100, 87 , -1
WRITE(*,*) K
END DO
Output:
100
99
98
...
...
...
87
The two loops are equivalent except in terms of the shape of the output. In the
implied loop version, the output will be printed on one line. In the explicit DO loop
72
version, the output will be printed as one value on each line.
3.5.9 The DO-CYCLE Construct
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.
Example 1:
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

Output

1
2
4
5

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
73
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 --> '
READ(*,*) Range
IF (Range < 2) THEN
WRITE(*,*) 'Input not in the required range'
CYCLE
END IF
... process Range ...
END DO

3.6 Exercises
74
1. What will be printed by the following programs?
1. PROGRAM Ex1_1
IMPLICIT NONE
INTEGER:: K, M, N
N = 0
DO K = -5 , 5
N = N + 2
DO M = 3 , 1
N = N + 3
END DO
N = N + 1
END DO
WRITE(*,*) N
END PROGRAM Ex1_1

2. PROGRAM Ex1_2
IMPLICIT NONE
INTEGER:: K, J
K = 2
25 IF ( K.GT.0 ) THEN
DO J = K, 3, 2
WRITE(*,*) K, J
END DO
K = K - 1
GOTO 25
ENDIF
END PROGRAM Ex1_2

3. PROGRAM Ex1_3
IMPLICIT NONE
INTEGER:: J, K
DO K = 1,2
WRITE(*,*) K
DO J = 1,3
WRITE(*,*)K,J
END DO
END DO
END PROGRAM Ex1_3

4. PROGRAM Ex1_4
IMPLICIT NONE
INTEGER:: X, K, M
M = 4
DO K = M ,M+2
X = M + 2
IF ( K<6 )THEN
WRITE(*,*)'HELLO'
ENDIF
END DO
END PROGRAM Ex1_4
2. Find the number of iterations of the WHILE-LOOPS in each of the following
programs:
75
1. PROGRAM number_1
IMPLICIT NONE
INTEGER:: K, M, J
K = 80
M = 5
J = M-M/K*K
10 IF ( J/= 0 ) THEN
WRITE(*,*)J
J = M-M/K*K
M = M + 1
GOTO 10
ENDIF
END PROGRAM number_1

2. PROGRAM number_2
IMPLICIT NONE
REAL:: W
INTEGER:: L
W = 2.0
L = 5 * W
100 IF ( L/W ==((L/4.0)*W) ) THEN
WRITE(*,*)L
L = L + 10
GOTO 100
ENDIF
END PROGRAM number_2

3. Which of the following program segments causes an infinite loop?


I. J = 0
25 IF ( J<5 ) THEN
J = J + 1
GOTO 25
ENDIF
WRITE(*,*)J
II. J = 0
25 IF ( J < 5 ) THEN
J = J + 1
ENDIF
GOTO 25
WRITE(*,*)J
III. X = 2.0
5 X = X + 1
IF ( X > 4 ) X = X + 1
GOTO 5
WRITE(*,*)X

4. Convert the following WHILE loops to DO loops :


I. ID = N
10 IF ( ID < 891234 ) THEN
WRITE(*,*)ID
ID = ID + 10
GOTO 10
ENDIF

76
II. L = 1
SUM =0
3 IF (L < 15) THEN
J = -L
2 IF (J < 0) THEN
SUM =SUM+J
J = J + 1
GOTO 2
ENDIF
L = L+3
GOTO 3
ENDIF
WRITE(*,*)SUM

5. What will be printed by the following program:


PROGRAM Ex_5
IMPLICIT NONE
INTEGER:: ISUM, K, N
ISUM = 0
READ(*,*) N
DO K = 1,N
ISUM = ISUM +(-1)**(K-1)
END DO
WRITE(*,*)ISUM
END PROGRAM Ex_5

If the input is:


a.
9
b.
51

6. The following program segments may or may not have errors. Identify the errors
(if any).
1. PROGRAM Ex6_1
IMPLICIT NONE
INTEGER:: K, J
DO K = 1,4
DO J = K-1,K
WRITE(*,*)K
END DO
END DO
END PROGRAM Ex6_1

2. PROGRAM Ex6_2
MPLICIT NONE
INTEGER:: K, J
K = 10
J = 20
1 IF ( J>K ) THEN

77
K = K/2
GOTO 1
ENDIF
END PROGRAM Ex6_2

7. Write a FORTRAN 77 program to calculate the following summation:


200
5k
 (( −1)
k
)
k =1 k +1

8. Write a program that reads the values of two integers M and then prints all the
odd numbers between the two integers. (Note: M may be less than or equal to N or
vice-versa).

9. Write a program that prints all the numbers between two integers M and N
which are divisible by an integer K. The program reads the values of M, N and K.

78
4. FUNCTIONS AND SUBROUTINES SUBPROGRAMS
Many problems consist of a number of tasks. One good technique in solving such
problems is to identify the tasks, decompose each task into sub-tasks and solve these
sub-tasks by smaller and simpler solutions.
4.1 Functions subprograms
In addition to intrinsic functions, Fortran allows you to design your own functions.
A Fortran function, or more precisely, a Fortran function subprogram, has the
following syntax:
type FUNCTION function-name (arg1, arg2, ..., argn)
IMPLICIT NONE
[specification part]
[execution part]
[subprogram part]
END FUNCTION function-name

• The first line of a function starts with the keyword FUNCTION. Before
FUNCTION, the type gives the type of the function value
(i.e., INTEGER, REAL, LOGICAL and CHARACTER) and after
FUNCTION is the name you assign to that function.
• Following the function-name, there is a pair of parentheses in which a number
of arguments arg1, arg2, ..., argn are separated with commas. These arguments
are referred to as formal arguments. Formal arguments must be variable names
and cannot be expressions. Here are some examples::
1. The following is a function called Factorial. It takes only one formal
argument n and returns an INTEGER as its function value.
INTEGER FUNCTION Factorial(n)
2. The following is a function called TestSomething. It takes three formal

arguments a, b and c, and returns a LOGICAL value

(i.e., .TRUE. or .FALSE.) as its function value.


LOGICAL FUNCTION TestSomething(a, b, c)
• A function must be ended with END FUNCTION followed by the name of
that function.

79
• Between FUNCTION and END FUNCTION, there are the IMPLICIT
NONE, specification part, execution part and subprogram part. These are
exactly identical to that of a PROGRAM.

If a function does not need any formal argument, it can be written as


type FUNCTION function-name ()
IMPLICIT NONE
[specification part]
[execution part]
[subprogram part]
END FUNCTION function-name
where arg1, arg2, ..., argn are left out. But, the pait of parenthesis must be there.

The meaning of a function is very simple:


• The function returns its result via the name of the function, somewhere in the
function there must exist one or more assignment statements like the following:
function-name = expression
where the result of expression is stored to the name of the function.
• To tell the function about the types of its formal arguments, all arguments must
be declared with a new attribute INTENT(IN). The meaning
of INTENT(IN) indicates that the function will only take the value from the
formal argument and must not change its content.
• Any statements that can be used in PROGRAM can also be used in
a FUNCTION.

4.1.1 Functions Examples


Here are a few examples of functions:
Example 1:
• The following function has a name Sum and three formal arguments a, b and c. It
returns an INTEGER function value. The INTEGER, INTENT(IN) part
indicates that the function takes its input value from its three formal argument.
Then, the function uses the value of these formal arguments to compute the sum
and stores in Sum, the name of the function. Since the next statement is END
FUNCTION, the function returns the value stored in Sum.

80
INTEGER FUNCTION Sum(a, b, c)
IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b, c

Sum = a + b + c
END FUNCTION Sum

Example 2:
• The following function has a name Positive with a REAL formal argument. If the
argument is positive, the function returns .TRUE.; otherwise, the function
returns .FALSE.
LOGICAL FUNCTION Positive(a)
IMPLICIT NONE

REAL, INTENT(IN) :: a

IF (a > 0.0) THEN


Positive = .TRUE.
ELSE
Positive = .FALSE.
END IF
END FUNCTION Positive

The above function can be made much shorter by using LOGICAL assignment.
Example 3:
• The following function GetNumber() does not have any formal arguments and
returns an INTEGER function value. This function has a DO-loop which keeps
asking the user to input a positive number. The input is read into the function name.
If this value is positive, then EXIT and the function returns the value
in GetNumber. Otherwise, the loop goes back and asks the user again for a new
input value.
REAL FUNCTION GetNumber()
IMPLICIT NONE

DO
WRITE(*,*) 'A positive real number --> '
READ(*,*) GetNumber
IF (GetNumber > 0.0) EXIT
WRITE(*,*) 'ERROR. Please try again.'
END DO
WRITE(*,*)
END FUNCTION GetNumber

81
4.1.2 Common Problems
• Forget the type of a FUNCTION.
FUNCTION DoSomething(a, b)
IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b

DoSomthing = SQRT(a*a + b*b)


END FUNCTION DoSomthing

If there is no type, you will not be able to determine if the returned value is
an INTEGER, a REAL or something else.
• Forget INTENT(IN).
REAL FUNCTION DoSomething(a, b)
IMPLICIT NONE
INTEGER :: a, b

DoSomthing = SQRT(a*a + b*b)


END FUNCTION DoSomthing

Actually, this is not an error. But, without INTENT(IN), our Fortran compiler will
not be able to check many potential errors for you.
• Change the value of a formal argument declared with INTENT(IN).
REAL FUNCTION DoSomething(a, b)
IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b
IF (a > b) THEN
a = a - b
ELSE
a = a + b
END IF
DoSomthing = SQRT(a*a + b*b)
END FUNCTION DoSomthing

Since formal argument a is declared with INTENT(IN), its value cannot be


changed.
• Forget to store a value to the function name.
REAL FUNCTION DoSomething(a, b)
IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b
INTEGER :: c

c = SQRT(a*a + b*b)
END FUNCTION DoSomthing
82
When the execution of this function reaches END FUNCTION, it returns the value
stored in DoSomething. However, in the above, since there is no value ever stored
in DoSmething, the returned value could be anything (i.e., a garbage value).
• Function name is used in the right-hand side of an expression.
REAL FUNCTION DoSomething(a, b)
IMPLICIT NONE
INTEGER, INTENT(IN) :: a, b

DoSomething = a*a + b*b


DoSomething = SQRT(DoSomething)
END FUNCTION DoSomthing

In the above, function name DoSomething appears in the right-hand side of the
second expression. This is a mistake. Only a special type of
functions, RECURSIVE functions, could have their names in the right-hand side
of expressions.
• Only the most recent value stored in the function name will be returned..
REAL FUNCTION DoSomething(a, b)
IMPLICIT NONE
INTEGER, INTENT(IN) :: a, b

DoSomething = a*a + b*b


DoSomething = SQRT(a*a - b*b)
END FUNCTION DoSomthing

In the above, the value of SQRT(a*a-b*b) rather than the value of a*a + b*b is
returned. In fact, this is obvious. Since the name of a function can be considered as
a special variable name, the second assignment overwrites the previous value.
4.1.3 Examples on function subprograms
Example 1: Write a real function VOLUME that computes the volume of a sphere
(4/3  r3) given its radius.
Solution:
REAL FUNCTION VOLUME(RADIUS)
IMPLICIT NONE
REAL, INTENT (IN):: RADIUS

REAL:: PI
PI = 3.14159
VOLUME = 4.0 / 3.0 * PI * RADIUS ** 3
END FUNCTION VOLUME

83
Example 2: Write a logical function ORDER that checks whether three different
integer numbers are ordered in increasing or decreasing order.
Solution:
LOGICAL FUNCTION ORDER(X, Y, Z)
IMPLICIT NONE
INTEGER INTENT (IN):: X, Y, Z
LOGICAL:: INC, DEC
DEC = X >Y .AND. Y >Z
INC = X < Y .AND. Y < Z
ORDER = INC .OR. DEC
END FUNCTION ORDER

Example 3: Write a function subprogram to evaluate the function f(x) defined below.
f(x) = 2x2 + 4x + 2 if x < 5
f(x) = 0 if x = 5
f(x) = 3x + 1 if x > 5
Solution:
REAL FUNCTION F(X)
IMPLICIT NONE
REAL INTENT (IN):: X
IF (X < 5) THEN
F = 2 * X ** 2 + 4 * X + 2
ELSEIF (X == 5) THEN
F = 0
ELSE
F = 3 * X + 1
ENDIF
END FUNCTION F

4.1.4 Function Call


Let us consider a program consisting of a main program and a function subprogram.
The execution of the program begins with the main program. For each call to a
function, control is transferred to the function.
When the execution of this function reaches END FUNCTION, it returns the value
stored in function-name, ensures that control is transferred back to the calling
program. The execution of the main program then resumes at the location the
function is called.
Example: In the following two tables, correct and incorrect function calls to the
functions defined in Examples 1, 2 and 3 are given. We assume that in the calling
program the function names VOLUME, F are declared as REAL, and ORDER as
LOGICAL. We also assume A = 5.0, B = 21.0, where A and B are real numbers:

84
Examples of correct function calls:
Function Call Function Value
ORDER(3, 2, 4) .FALSE.
ORDER(3, 4 * 3, 99) .TRUE.
F(A) 0.0
F(3 + F(2.0)) 64.0
VOLUME(B) 38808.0
F(A + B) 79.0

Examples of incorrect function calls:


Incorrect Error Message
Function Call
ORDER(3.0,2, 4) Argument 1 referenced as real but defined to be integer
F(3.2, 3.4) More than one argument to function F
VOLUME(5) Argument 1 referenced as integer but defined to be real

4.1.5 Function Rules


The following rules must be observed in writing programs with function
subprograms:
• Actual and dummy arguments must match in type, order and number. The
names of these arguments may or may not be the same.
• Actual arguments may be expressions, constants or variable names. Dummy
arguments must be variable names and should never be expressions or constants.
• The type of the function name must be the same in both the calling program
and the function description.
• The result from the function subprogram, to be returned to the calling
program, should be stored in the function name.
• A function is called or invoked as part of an expression.
• A FORTRAN function cannot call itself.
• For a formal argument declared with INTENT(IN), any attempt to change
its value in the function will cause a compiler error. The meaning
of INTENT(IN) is that this formal argument only receives a value from its
corresponding actual argument and its value cannot be changed.
85
• Based on the previous point, if a formal argument is declared without using
INTENT(IN), its value can be changed. For writing functions, this is not a good
practice and consequently all formal arguments should be declared with
INTENT(IN).

4.1.6 Complete Examples on function subprograms


Example 1: The sum of three integer numbers: Write an integer function SUM to
sum three integer numbers. Also write a main program to test the function SUM.
Solution:
! MAIN PROGRAM
PROGRAM SUM
IMPLICIT NONE
INTEGER:: X, Y, Z, SUM
READ(*,*) X, Y, Z
WRITE(*,*) SUM (X, Y, Z)
END PROGRAM SUM

! FUNCTION SUBPROGRAM
INTEGER FUNCTION SUM(A, B, C)
IMPLICIT NONE
INTEGER INTENT (IN):: A, B, C
SUM = A + B + C
END FUNCTION SUM

The execution starts with the reading of variables X, Y and Z in the main program.
The execution of the expression SUM(X, Y, Z) transfers control to the function
SUM. The value of the actual arguments X, Y and Z is passed to the dummy
arguments A, B and C respectively. In the function SUM, execution begins with the
first executable statement which computes the value of SUM. The return statement
returns control to the main program. The print statement in the main program prints
the value of SUM(X, Y, Z) and the execution ends. Assume that the input to the
above program is as follows:
7 3 9
then the output of the program is
19

Programming Examples:
Example1:
86
We shall use the following function to illustrate the above rules.
Function Small() takes three formal arguments x, y and z and returns the value of
the smallest.
INTEGER :: a, b, c NTEGER FUNCTION Small(x, y, z)
IMPLICIT NONE
a = 10 INTEGER, INTENT(IN) :: x, y, z
b = 5
c = 13 IF (x <= y .AND. x <= z) THEN
WRITE(*,*) Small(a,b,c) Small = x
WRITE(*,*) Small(a+b,b+c,c) ELSE IF (y <= x .AND. y <= z) THEN
WRITE(*,*) Small(1, 5, 3) Small = y
WRITE(*,*) Small((a),(b),(c)) ELSE
Small = z
END IF
END FUNCTION Small
In the first WRITE, x, y and z in function Small() receives 10, 5 and 13,
respectively.
In the second WRITE, x, y and z receive 15, 18 and 13 respectively.
In the third WRITE, x, y and z receive 1, 5 and 3 respectively.
In the fourth WRITE, x, y and z receive 10, 5 and 13, respectively.

Example2:
Computing Cubes
Write a program to compute the cubes of 1, 2, 3, ..., 10 in
both INTEGER and REAL types. It is required to write a function intCube() for
computing the cube of an integer and a function realCube() for computing the
cube of a real.
Solution
PROGRAM Cubes
IMPLICIT NONE
INTEGER, PARAMETER :: Iterations = 10
INTEGER :: i
REAL :: x

DO i = 1, Iterations
x = i
WRITE(*,*) i, x, intCube(i), realCube(x)
END DO
END PROGRAM Cubes

! -----------------------------------------------------
! INTEGER FUNCTION intCube() :
87
! This function returns the cube of the argument.
! -----------------------------------------------------
INTEGER FUNCTION intCube(Number)
IMPLICIT NONE
INTEGER, INTENT(IN) :: Number

intCube = Number*Number*Number
END FUNCTION intCube

! -----------------------------------------------------
! REAL FUNCTION realCube() :
! This function returns the cube of the argument.
! -----------------------------------------------------
REAL FUNCTION realCube(Number)
IMPLICIT NONE
REAL, INTENT(IN) :: Number

realCube = Number*Number*Number
END FUNCTION realCube

Program Input and Output


The following is the output from the above program.
1, 1., 1, 1.
2, 2., 8, 8.
3, 3., 27, 27.
4, 4., 64, 64.
5, 5., 125, 125.
6, 6., 216, 216.
7, 7., 343, 343.
8, 8., 512, 512.
9, 9., 729, 729.
10, 10., 1000, 1000.

4.1.7 Statement Functions


In engineering and science applications, we frequently encounter functions that can
be written in a single statement. For example, is a simple function. In such cases,
FORTRAN allows us to write a statement function instead of writing a function
subprogram. A statement function is defined in the beginning of a program after
declaration statements. As a non-executable statement, it should appear before any
executable statement. The general form of this statement is as follows:
fname (a list of arguments) = expression
where
fname is the name of the function;
a list of arguments is the optional list of dummy arguments; and
88
expression computes the function value. The type of the statement function may
be declared in the declaration statements. If the type of the function is not declared,
it is implicitly defined.

Examples of statement functions:


Example 1: Write a statement function to compute the area of a triangle, given its
two sides and an angle.
REAL AREA
AREA(SIDE1,SIDE2,ANGLE) = 0.5*SIDE1 * SIDE2 *SIN (ANGLE)

Example 2: Write a statement function to compute the total number of seconds,


given the time in hours, minutes and seconds.
Solution:
REAL TOTSEC
TOTSEC(HOUR,MINUTE,SECOND) = 3600*HOUR +60*MINUTE + SECOND

Example 3: Write a statement function to compute the function


f(x,y) = 3x2 + 5xy
Solution:
REAL F
F(X,Y) = 3 * X ** 2 + 5 * X * Y

Example 4: Write a logical statement function to check if three different integer


numbers are in increasing or decreasing order.
Solution:
LOGICAL :: ORDER
RDER(X,Y,Z) = X > Y .AND. Y > Z.OR.X<Y.AND. Y<Z
Example 5: Temperature Conversion: Convert temperatures from one unit into
another using statement functions. Write a main program to test the functions based
on a code. If the code is 1, convert from centigrade to Fahrenheit. If code is 2,
convert from Fahrenheit to centigrade. Otherwise, print an error message.
Solution:
PROGRAM Temperature
IMPLICIT NONE
REAL :: FTEMP, CTEMP, TEMP, VALUE
INTEGER :: CODE
! FUNCTION FTEMP CONVERTS FROM CENTIGRADE TO FAHRENHEIT
FTEMP(TEMP) = TEMP * 9 / 5 + 32
! FUNCTION CTEMP CONVERTS FROM FAHRENHEIT TO CENTIGRADE
CTEMP(TEMP) = (TEMP - 32) * 5 / 9
READ(*,*) CODE, VALUE
IF (CODE == 1) THEN
WRITE(*,*)VALUE , ' C = ' , FTEMP(VALUE), ' F'
ELSEIF (CODE == 2) THEN

89
WRITE(*,*)VALUE , ' F = ' , CTEMP(VALUE), ' C'
ELSE
WRITE(*,*)'INPUT ERROR'
ENDIF
END Temperature

The statement functions FTEMP and CTEMP convert the argument value to
Fahrenheit and centigrade respectively. The statement functions are placed
immediately after the declaration statements. The variables CODE and VALUE are
read. Based on the value of CODE, the appropriate statement function is invoked
and the converted value is printed.

4.2 Subroutine Subprograms


A function produces a single result. In many instances, we would like a subprogram
to produce more than one result. Subroutines are designed to produce zero, one or
many results. Subroutines differ from functions in the following ways:
• A subroutine may return a single value, many values, or no value.
• To return results, the subroutine uses the argument list; thus, the subroutine
argument list consists of input arguments and output arguments.
• Since the results are returned through arguments, a subroutine name is used
for documentation purposes only and does not specify a value.
• The general form of the subroutine is as follows:

SUBROUTINE subroutine-name (arg1, arg2, ..., argn)


IMPLICIT NONE
[specification part]
[execution part]
[subprogram part]
END SUBROUTINE subroutine-name

• The first line of a subroutine starts with the keyword SUBROUTINE, followed by
that subroutine's name.
• Following subroutine-name, there is a pair of parentheses in which a number of
arguments arg1, arg2, ..., argn are separated with commas. These arguments are
referred to as formal arguments. Formal arguments must be variable names and
cannot be expressions and constants. Here are examples:
90
1. The following is a subroutine called Factorial. It has two formal
arguments n and Answer.
SUBROUTINE Factorial (n, Answer)
2. The following is a subroutine called TestSomething. It takes four formal
arguments a, b, c, and Error.
SUBROUTINE TestSomething(a, b, c, Error)
• A subroutine must end with END SUBROUTINE, followed by its name.
• Between SUBROUTINE and END SUBROUTINE, there are IMPLICIT
NONE, specification part, execution part and subprogram part. These are
exactly identical to that of a PROGRAM.
• Subroutines can be internal to a program. Subroutine can also be external and in
this case INTERFACE blocks are required.
If a subroutine does not need any formal argument, it can be written as
SUBROUTINE subroutine-name ()
IMPLICIT NONE
[specification part]
[execution part]
[subprogram part]
END SUBROUTINE subroutine-name

where arg1, arg2, ..., argn are left out.


Unlike functions, the pair of parentheses can be removed:
SUBROUTINE subroutine-name
IMPLICIT NONE
[specification part]
[execution part]
[subprogram part]
END SUBROUTINE subroutine-name

The meaning of a subroutine is very simple:


• A subroutine is a self-contained unit that receives some "input" from the outside
world via its formal arguments, does some computations, and then returns the results,
if any, with its formal arguments.

91
• Unlike functions, the name of a subroutine is not a special name to which you can
save a result. Subroutine's name is simply a name for identification purpose and you
cannot use it in any statement except the CALL statement.
• A subroutine receives its input values from its formal arguments, does computations,
and saves the results in some of its formal arguments. When the control of execution
reaches END SUBROUTINE, the values stored in some formal arguments are
passed back to their corresponding actual arguments.
• Any statements that can be used in a PROGRAM can also be used in
a SUBROUTINE.

4.2.1 Arguments’INTENT
We have three cases to consider:
• If an argument only receives value from outside of the subroutine, it still has its intent
like INTENT(IN). This is the simplest case.
• An argument does not have to receive anything from outside of the subroutine. It can
be used to pass a computation result back to the outside world. In this case, its intent
becomes INTENT(OUT). In a subroutine, an argument declared
with INTENT(OUT) is supposed to hold a computation result so that its value can
be passed "out".
• Finally, an argument can receive a value, use it for computation, and hold a result so
that it can be passed back to the outside world. In this case, its intent
is INTENT(INOUT).
An argument must be declared
with INTENT(IN), INTENT(OUT) or INTENT(INOUT).
Examples
Here are some examples:
Example 1:
• The following subroutine Means() has six arguments. Arguments a, b and c are
declared with INTENT(IN) and therefore can only take values from outside world
and cannot be changed. Arguments Am, Gm and Hm are declared
with INTENT(OUT), indicating that their values will be computed and passed to
92
the outside world. More precisely, in subroutine Means(), some values must be
stored into these three arguments so that they can be passed out. Note that an
argument declared with INTENT(OUT) does not have to receive any value from
outside of the subroutine.
SUBROUTINE Means(a, b, c, Am, Gm, Hm)
IMPLICIT NONE
REAL, INTENT(IN) :: a, b, c
REAL, INTENT(OUT) :: Am, Gm, Hm
..........
END SUBROUTINE Means

Example 2:
• The following subroutine Swap() has its both arguments declared with
INTENT(INOUT). That means, a and b will receive some values, after some
processing a new set of values will replace the given one so that they can be passed
back.
SUBROUTINE Swap(a, b)
IMPLICIT NONE
INTEGER, INTENT(INOUT) :: a, b
..........
END SUBROUTINE Swap

4.2.2 The CALL Statement


Unlike functions, which can be used in expressions, subroutines can only be called
with the CALL statement. That means, the call to a subroutine must be on its
program line rather than somewhere in an expression. The following is the syntax
rules of the CALL statement:
CALL subroutine-name (arg1, arg2, ..., argn)
CALL subroutine-name ()
CALL subroutine-name

If the called subroutine has formal arguments, the CALL statement that calls that
subroutine must have actual argument. This is the first form. However, if a
subroutine does not have any argument, it can be called with the second form or the
third form.

93
Examples on Subroutine Subprograms:
Here are some simple examples:
Example 1: Write a subroutine that exchanges the value of its two real arguments.
Solution:
SUBROUTINE EXCHNG(NUM1, NUM2)
IMPLICIT NONE
REAL, INTENT(INOUT) :: NUM1, NUM2
REAL :: TEMP
TEMP = NUM1
NUM1 = NUM2
NUM2 = TEMP
END SUBROUTINE EXCHNG

The subroutine EXCHNG can be invoked using the CALL statement.


An example illustrating a call to the subroutine EXCHNG is given below: Assume
the variables X, Y are declared as real in the calling program and have the values 3.0
and 8.0 respectively. The CALL statement
CALL EXCHNG(X, Y)
after execution will exchange the value of X and Y. When the RETURN statement
of the subroutine is executed, the control returns to the calling program and the new
values of variables NUM1 and NUM2 are passed back to the actual arguments X
and Y respectively. Therefore, the new value of variable X would be 8.0 and the
value of variable Y would be 3.0.
Example 2: Write a subroutine that takes three different integer arguments X, Y and
Z and returns the maximum and the minimum.
Solution:
SUBROUTINE MINMAX(X, Y, Z, MAX, MIN)
IMPLICIT NONE
INTEGER, INTENT(IN) :: X, Y, Z
INTEGER, INTENT(OUT) :: MAX, MIN
MIN = X
MAX = X
IF (Y >MAX) MAX = Y
IF (Y < MIN) MIN = Y
IF (Z >MAX) MAX = Z
IF (Z < MIN) MIN = Z
END SUBROUTINE MINMAX
Examples illustrating calls to the subroutine MINMAX is given below:
• Assume the variables A, B, C are declared as integer in the calling program and

94
have the values 4, 6, 8 respectively. Also assume that MAX and MIN are integer
variables. After the following CALL statement
CALL MINMAX(A, B, C, MAX, MIN)
is executed, the value of MAX will be 8 (the maximum of variables A, B, C) and
the value of MIN will be 4 (the minimum of variables A, B, C). Note that the names
of the actual arguments may be similar or different from the corresponding
dummy arguments but the type must be the same.
• If the following CALL statement
CALL MINMAX(C+4, -1, A+B, MAX, MIN)
is executed, the value of MAX will be 12 and the value of MIN will be -1, since the
first three actual arguments in the CALL statement are evaluated to 12, -1 and 10
respectively. Note here that the actual arguments can be expressions.
Example 3:
• The following has a subroutine Larger() whose job is returning the larger one of
the first two arguments with the third argument.
The main program calls subroutine Larger() with a CALL statement.
PROGRAM Example1 SUBROUTINE Larger(u, v, w)
IMPLICIT NONE IMPLICIT NONE
INTEGER a, b, c INTEGER, INTENT(IN) :: u, v
......... INTEGER, INTENT(OUT) :: w
CALL Larger(a, b, c) IF (u > v) THEN
......... w = u
END PROGRAM Example1 ELSE
w = v
END IF
END SUBROUTINE Larger

Example 4:
• In the following program, subroutine DoSomething() takes three formal
arguments. If p is greater than 3, then adds 1 to q and puts 1 into r. If p is less
then -3, then 1 is subtracted from q and 2 is stored to r. Otherwise, r receives 3
and the value of q is unchanged.
For the main program, if the value read into a is 7, then the CALL will receive 1
for b and 1 for c. If the value read into a is -4, b and c should receive -1 and 2
from subroutine DoSomething(). If a receives a value of 2, since q is not
changed
95
in DoSomething(), b and c receive 0 (unchanged) and 3, respectively.

PROGRAM Example3 SUBROUTINE DoSomething(p, q, r)


IMPLICIT NONE IMPLICIT NONE
INTEGER :: a, b, c INTEGER, INTENT(IN) :: p
.......... INTEGER, INTEGER(INOUT) :: q
READ(*,*) a INTEGER, INTENT(OUT) :: r
b = 0 IF (p > 3) THEN
CALL DoSOmething(a,b,c) q = q + 1
WRITE(*,*) a, b, c r = 1
.......... ELSE IF (p < -3) THEN
END PROGRAM Example3 q = q - 1
r = 2
ELSE
r = 3
END IF
END SUBROUTINE DoSomething

Programming Example: Computing Means -


The arithmetic, geometric and harmonic means of three positive numbers are
defined by the following formulas:

Write a program to read three positive numbers and use a single internal subroutine
to compute the arithmetic, geometric and harmonic means.
Solution
! ----------------------------------------------------------
! This program contains one subroutine for computing the
! arithmetic, geometric and harmonic means of three REALs.
! ----------------------------------------------------------

PROGRAM Mean
IMPLICIT NONE

REAL :: u, v, w
REAL :: ArithMean, GeoMean, HarmMean

READ(*,*) u, v, w

CALL Means(u, v, w, ArithMean, GeoMean, HarmMean)

WRITE(*,*) "Arithmetic Mean = ", ArithMean


WRITE(*,*) "Geometric Mean = ", GeoMean
WRITE(*,*) "Harmonic Mean = ", HarmMean
96
END PROGRAM Mean

! ----------------------------------------------------------
! SUBROUTINE Means():
! This subroutine receives three REAL values and computes
! their arithmetic, geometric, and harmonic means.
! ----------------------------------------------------------

SUBROUTINE Means(a, b, c, Am, Gm, Hm)


IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c
REAL, INTENT(OUT) :: Am, Gm, Hm

Am = (a + b + c)/3.0
Gm = (a * b * c)**(1.0/3.0)
Hm = 3.0/(1.0/a + 1.0/b + 1.0/c)
END SUBROUTINE Means

Program Input and Output

The following is the output from the above program for the input
3.0, 6.0 and 8.0:
Arithmetic Mean = 5.66666651
Geometric Mean = 5.24148321
Harmonic Mean = 4.80000019

97
4.3 Exercises
1. Which of the following statement(s) is (are) FALSE?
1. A subroutine may return one value, many values, or no value.
2. A subroutine cannot call itself in FORTRAN.
3. The statement function is a non-executable statement.
4. A function may return more than one value.
5. A program may contain more than one subprogram.
6. A subroutine cannot call another subroutine.

2. What is printed by the following programs ?


1. PROGRAM EX2_1
IMPLICIT NONE
INTEGER:: A, B, X, Y, Z, F
A = 2
B = 3
X = F(4, A)
Y = B * 3
Z = F(Y, X)
WRITE(*,*) X, Y, B, Z
END PROGRAM EX2_1
INTEGER FUNCTION F(X,Y)
IMPLICIT NONE
INTEGER, INTENT(IN) :: X,Y
INTEGER :: Z
Z = 2*Y
F = X+Z
END FUNCTION F
2. PROGRAM EX2_2
IMPLICIT NONE
LOGICAL:: DIV
INTEGER:: N, J
READ(*,*) N, J
IF (DIV(N, J))THEN
WRITE(*,*) 'YES'
ELSE
WRITE(*,*) 'NO'
ENDIF
END PROGRAM EX2_2
LOGICAL FUNCTION DIV(N, J)
IMPLICIT NONE
INTEGER, INTENT(IN) :: N, J
DIV = N - N / J * J .EQ. 0
END FUNCTION DIV

Assume the input is


18 4

98
3. PROGRAM EX2_3
IMPLICIT NONE

INTEGER:: K , EVL
K = 1
WRITE(*,*) EVL (K), K
END PROGRAM EX2_3

INTEGER FUNCTION EVL (M)


IMPLICIT NONE
INTEGER, INTENT(IN) :: M
INTEGER :: K
K = 2
EVL = M * K
END FUNCTION EVL

4. PROGRAM EX2_4
IMPLICIT NONE
INTEGER A, B
REAL FUN
READ(*,*)A, B
A = FUN(A, B)
B = FUN(B, A)
WRITE(*,*) FUN(A, B)
END PROGRAM EX2_4

REAL FUNCTION FUN(X, Y)


IMPLICIT NONE
INTEGER, INTENT(IN) :: X, Y
INTEGER:: X, Y
FUN = X ** 2 + 2 * Y
END FUNCTION FUN
Assume the input is
1, 2

5. PROGRAM EX2_5
IMPLICIT NONE
INTEGER:: K, L
K = -9
L = 10
WRITE(*,*) MOD(ABS(K),L)
END PROGRAM EX2_5

6. PROGRAM EX2_6
IMPLICIT NONE
REAL :: A, B, DIST, X, Y
DIST(X,Y) = SQRT(X ** 2 + Y ** 2)
READ(*,*)A, B
WRITE(*,*) DIST(A - 3.0, DIST(A, B) - 6.0)
END PROGRAM EX2_6
Assume the input is

99
6.0 8.0

7. PROGRAM EX2_7
IMPLICIT NONE
REAL ::F, G, A, B, X, Y
F(A , B) = A + B
G(X) = X ** 2
READ(*,*)Y
WRITE(*,*) G(Y), G(F(Y, Y + 2))
END PROGRAM EX2_7
Assume the input is
3.0
8. PROGRAM EX2_8
IMPLICIT NONE
LOGICAL :: COMP
REAL :: X, Y, Z, A, B, C
COMP(A, B, C) = A. GE. B .AND. A .GE. C
READ(*,*)X, Y, Z
IF (COMP(X, Y, Z)) WRITE(*,*) X
IF (COMP(Y, X, Z)) WRITE(*,*) Y
IF (COMP(Z, X, Y)) WRITE(*,*) Z
END PROGRAM EX2_8
Assume the input is
35.0 90.0 65.0

3. Write a logical function subprogram FACTOR that takes two arguments and
checks if the first argument is a factor of the second argument. Write a main program
to test the function.

4. Write a function subprogram to reverse a three-digit number. For example, if the


number is 243, the function returns 342. Write a main program to test the function.

5. Write a function subprogram called AREA to compute the area of a circle. The
argument to the function is the diameter of the circle. Write a main program to test
the function.

6. Write a logical function subprogram that checks whether all its three arguments
are non-zero. Write a main program to test the function.

7. Consider the following statement function IXX (J,K) = J-J/K*K. Which one of the
following intrinsic (built-in) functions is the same as the function IXX ?
i) MOD
ii) MAX
iii) MIN
iv) SQRT

100
5. Arrays
It is fairly common in programs to read a large quantity of input data, process the
data and produce the computations as output. Use array to store Such large amounts
of input data , all of the same type.
A one-dimensional array represents a group of memory locations. Each member
of an array is called an element. An element in an array is accessed by the array name
followed by a subscript (also called an index) enclosed in parentheses.
Arrays can be one- dimensional (like vectors), two-dimensional array (like
matrices). An element in a two-dimensional array is addressed by its row and
column; for example, X(3,2) refers to the element in row 3 and column 2 which has
a value 6 and Fortran allows you to create up to 7-dimensional arrays.

Numbers(1) Numbers(2) Numbers(3) Numbers(4) …

one- dimensional array

X(1,1) X(1,2) X(1,3)

X(2,1) X(2,2) X(2,3)

two-dimensional array

A one-dimensional array has the following important components:


• A name
• A type: this is the type of all array elements.
• An extent: this is the range of the indices or subscripts of array elements. For
example, the range of an array can be 1 to 10 (i.e., elements 1, element 2,
elements 3, ..., element 10) or -3 to 5 (i.e., element -3, element -2, ..., element
4, element 5).
Indices or subscripts must be integers within the range. The smallest and the
largest indices or subscripts are referred to as the lower bound and
the upper bound, respectively.
• The extent of an array is simply the following:
101
smaller-integer : larger-integer
where smaller-integer and larger-integer are the lower bound and the upper
bound of the extent. Thus, if array indices are in the range of 0 and 11, the extent
is 0:11; if array indices are in the range of -3 and 21, the extent is -3:21.
However, if the lower bound of an extent is 1, it can be omitted as well as the
colon following it.
5.1 Array Declaration
Arrays must be declared using a declaration statement.
The syntax for declaring arrays is the following:

type, DIMENSION( extent ) :: name-1, name-2, ..., name-n


For example, suppose we have the following array declarations:
REAL, DIMENSION(-1:1) :: a, Sum
INTEGER, DIMENSION(0:100) :: InputData

• The elements of arrays a and Sum are REALs and the indices are in the range
of -1 and 1.
• The elements of array InputData are INTEGERs and the indices are in the
range of 0 and 100.
LOGICAL, DIMENSION(1:100) :: AnswerSheet
REAL, DIMENSION(10:10) :: Score, Mark

In the above, the range of array AnswerSheet is 1 and 100, while the range of
arrays Score and Mark is -10 and 10.

We can declare arrays of any type. There are two common notations for declaring
array variables: using the dimension attribute or by appending the array dimensions
in parentheses to the variable name.
Example: static array declaration
program arrays
implicit none
! 1D integer array
integer, dimension(10) :: array1
! An equivalent array declaration
integer :: array2(10)
! 2D real array
real, dimension(10, 10) :: array3

102
! Custom lower and upper index bounds
real :: array4(0:9)
real :: array5(-5:5)
end program arrays
The following declarations are equivalent. Both declare an integer array a with 6
elements; an array b with 10 real elements and a logical 2-dimensional array named
yes_no.
INTEGER, DIMENSION(6) :: a
REAL, DIMENSION(0:9) :: b
LOGICAL, DIMENSION(2,2) :: yes_no
INTEGER :: a(6)
REAL :: b(0:9)
LOGICAL :: yes_no(2,2)

Use the dimension attribute form when several arrays of the same bounds and type
need to be declared. Use second form when several arrays of the same type but
different bounds need to be declared. The choice is influenced by the style followed
by the programmer but certain circumstances might dictate the use of one form rather
than another.
A mixture of the two forms in the same program is allowed. Some further examples
are shown below:
INTEGER, DIMENSION(8) :: x,y
REAL:: alpha(1:3), beta(4:9)
REAL, DIMENSION(0:5,12:45,6) :: data
CHARACTER(len=10) :: names(25)
The first example declares two arrays of the same dimension and type, therefore the
dimension attribute form is employed. The second example declares two arrays of
the same type but different dimension hence the array specification form is followed.
For the third and fourth examples any of the two forms could have been used. The
fourth example declares an array which has 25 elements with each element having a
character string of size 10.
Array Elements
An element of an array has a form of the following:
array-name ( integer-expression )
For example, suppose we have the following array declarations:
REAL, DIMENSION(-1:1) :: a, Sum
INTEGER, DIMENSION(0:100) :: Input

103
Consider array a declared above. Its elements are a(-1), a(0) and a(1). The elements
of array Input are Input(0), Input(1), …., Input(100). Moreover, if integer
variables i and j have values 3 and 8, respectively, Input(j-i) is equivalent
to Input(5), Input(i*j) is equivalent to Input(24).
However, Input(3.0) is incorrect, since array index or subscript must be integers.
The value of the integer-expression used as an index or subscript for an array
element must be in the range of the extent used to declare the array.
Examples:
Example 1: Declaration of an integer array LIST consisting of 20 elements.
INTEGER, DIMENSION (20) :: LIST
Example 2: Declaration of a logical array FLAG that consists of 30 elements.
LOGICAL, DIMENSION(30):: FLAG
Example 3 : Declaration of a character array CITIES that consists of 9 elements in
3 rows and 3 columns and each element is of size 15.
CHARACTER(LEN=15) :: CITIES (3,3)
5.2 Implied DO
Implied DO-loops provide a fast way of listing many items. These items, depending
on the place where an implied DO is used, can be variables, expressions, or even
implied DO-loops.
The syntax of an implied DO is the following:
( item-1, item-2, ...., item-n, DO-var = initial, final, step )

( item-1, item-2, ...., item-n, DO-var = initial, final )

Depending on the place where an implied DO is used, the items can be variables,
including array elements, or expressions.
Example
• In the following, the DO variable is i and the items are a(i) and b(i+1).
( a(i), b(i+1), i = 1, 3 )
For i=1, the listed items are a(1) and b(2). For i=2, the listed items are a(2)
and b(3). For i=3, the listed items are a(3) and b(4). In summary, there are six
items listed as i goes from 1 to 3:

104
a(1), b(2), a(2), b(3), a(3), b(4)

5.3 Array Input/Output


Input
The easiest way of reading data into an array could be the following:
INTEGER, DIMENSION(1:10) :: x
INTEGER :: n, i

READ(*,*) n
DO i = 1, n
READ(*,*) x(i)
END DO

In this case, if the input to n is 5. the READ(*,*) statement in the DO-loop executes
5 times. Therefore, excluding the input for n, five input lines are required.
However, the implied DO can simplify this greatly. Consider the following
example:
INTEGER, DIMENSION(1:10) :: x
INTEGER :: n, i

READ(*,*) n
READ(*,*) (x(i), i=1, n)

If the value of n is 5, the implied DO in the READ(*,*) is expanded to


x(1), x(2), x(3), (4), x(5)
Therefore, the READ(*,*) statement is actually equivalent to
INTEGER, DIMENSION(1:10) :: x
INTEGER :: n, i

READ(*,*) x(1), x(2), x(3), x(4), x(5)

Consider the following two input files:


File #1 File #2
------- -------
5 5
10 10 30 20 40 50
30
20
40
50

and the following two READ(*,*)s:

105
READ #1 READ #2
======= =======
INTEGER,DIMENSION(1:10) :: x INTEGER,DIMENSION(1:10) :: x
INTEGER :: n, i INTEGER :: n, i

READ(*,*) n READ(*,*) n
DO i = 1, n READ(*,*) (x(i), i=1, n)
READ(*,*) x(i)
END DO
READ #1 can certainly reads in File #1 correctly. The result is

n x(1) x(2) x(3) x(4) x(5)

5 10 30 20 40 50

READ #2 can certainly reads in File #2 correctly. Using READ #2 to read File
#1 would get the same result.
It is interesting to remind you that the following READ #3 can successfully read
in File #1 and File #2. Why?
READ #3
=======
INTEGER, DIMENSION(1:10) :: x
INTEGER :: n, i

READ(*,*) n, (x(i), i=1, n)

Example 1: Read an integer one-dimensional array of size 100.


Solution 1: (Using a WHILE Loop)
INTEGER:: A(100), K
K = 0
66 IF (K<100) THEN
K = K + 1
READ(*,*)A(K)
GOTO 66
ENDIF
Note that we require 100 lines of input with one data value per line since the READ
statement is executed 100 times.
Solution 2: (Using a DO Loop)
INTEGER A(100), K
DO K = 1, 100
READ(*,*)A(K)
END DO

106
Note again that we require 100 lines of input with one data value per line since the
READ statement is executed 100 times.
Solution 3: (Using an implied Loop)
INTEGER:: A(100), K
READ(*,*)(A(K), K = 1, 100)

Note that we require one line with 100 data values since the READ statement is
executed only once. Even if the input is given in 100 lines with one data value per
line, the implied loop will correctly read the input.
Output
Consider the following example:
INTEGER, DIMENSION(1:10) :: x, y
INTEGER :: n = 5, i
DO i = 1, 5
WRITE(*,*) x(i), y(i)
END DO

WRITE(*,*) (x(i), y(i), i=1, n)

The first WRITE(*,*) is executed five times. Each time, it reads in two integers, one
for x(i) and the other for y(i). Thus, the output is on five different lines.
The second WRITE(*,*) is equivalent to
INTEGER, DIMENSION(1:10) :: x, y
INTEGER :: n = 5, i

WRITE(*,*)x(1),y(1),x(2),y(2),x(3)y(3),x(4),y(4),x(5),y(5)

Therefore, the ten output values are on the same line.


Example1 : Read an integer array X of size 4 and print:
i. the entire array X in one line;
ii. one element of array X per line; and
iii. array elements greater than 0.

Solution:
PROGRAM OUTPUT_1
IMPLICIT NONE
INTEGER, DIMENSION(4) :: x
INTEGER:: K
READ(*,*)X
! PRINTING THE ENTIRE ARRAY IN ONE LINE
WRITE(*,*) 'PRINTING THE ENTIRE ARRAY'
107
WRITE(*,*) X
! PRINTING ONE ARRAY ELEMENT PER LINE
WRITE(*,*) 'PRINTING ONE ARRAY ELEMENT PER LINE'
DO K = 1, 4
WRITE(*,*) X(K)
END DO
! PRINTING ARRAY ELEMENTS GREATER THAN 0
WRITE(*,*) 'PRINTING ARRAY ELEMENTS GREATER THAN 0'
DO K = 1, 4
IF(X(K) >0) WRITE(*,*) X(K)
END DO
END PROGRAM OUTPUT_1
If the input is given as
7, 0, 2, -4
the output of the program is as follows:
PRINTING THE ENTIRE ARRAY
7 0 2 -4
PRINTING ONE ARRAY ELEMENT PER LINE
7
0
2
-4
PRINTING ARRAY ELEMENTS GREATER THAN
7
2

5.4 Errors in Using Arrays


There are many errors that may occur in the use of arrays. These errors may appear,
if the following rules are not followed:
• Array subscripts must not go beyond the array boundaries.
• Array subscripts must always appear as integer expressions.
• Arrays must be declared before its elements are initialized.
The following errors are commonly seen while using arrays :
1. Array declaration is missing: All arrays must be declared. Otherwise, a
message would appear as 'FUNCTION array name IS NOT DEFINED.' Since
the array declaration is missing, the computer assumes it to be a function.
Therefore, the misleading message appears.
2. Array subscript is out-of-bounds: This error occurs when an array subscript is
outside the range of the array elements. For example, for a one-dimensional array
X declared as INTEGER X(10), the expression X(12) would produce an error.
Similarly, in a 2-D array Y declared as INTEGER Y (-3:2, 5), the expression
108
Y(-5,1) would produce an error.
3. Array subscript is not an integer: All array subscripts must be integers. This
error occurs when an array subscript is real. For example, for a one-dimensional
array X declared as INTEGER X(10), the expression X(2.0) would produce an
error. Similarly, in a 2-D array Y of size 3x2, an expression Y(1,3.0) would
produce an error.
We will now illustrate a few errors through examples. Assume the following
declarations:
INTEGER :: GRADE(25), LIST(3)
LOGICAL :: MEM(20)
CHARACTER :: TEXT(5) * 3
The following statements illustrate incorrect initializations of arrays:
Initialization Type of Error
GRADE(26) = 0.0 array subscript 26 is out of range
LIST(2.0) = X * 3 array subscript 2.0 is not an integer
TEXT(4) = 100 array TEXT is a character array
MEM(3) = 'WRONG' array MEM is a logical array
READ(*,*)(GRADE(K), K = 1, 100) array GRADE has only 25 elements
ARR(2) = 3 ARR is not declared as an array

5.5 Complete Examples :


Example 1: Counting Odd Numbers: Read an integer N and then read N data values
into an array. Print the count of those elements in the array that are odd.
Solution:

PROGRAM Counting
IMPLICIT NONE
INTEGER, DIMENSION(50) :: A
INTEGER:: COUNT, N , K
READ(*,*)N, (A(K), K = 1, N)
COUNT = 0
DO K = 1, N
IF (MOD (A(K), 2) .EQ. 1) COUNT = COUNT + 1
END DO
WRITE(*,*) 'COUNT OF ODD ELEMENTS = ', COUNT
END PROGRAM Counting
If the input is:
7, 35, 66, 83, 22, 33, 1, 89
The value of variable N in this example is 7. The next seven input data values are
109
placed in the array. There are 5 odd values among the seven elements of the array.
For the given input, the output is as follows:
COUNT OF ODD ELEMENTS = 5
Example 2: More on Reading Two-Dimensional Arrays: Write a FORTRAN
program that reads a two dimensional array of size 5 x 4 row-wise. Each value is
read from a separate line of input. The program then prints the same array column-
wise such that the elements of the first column are printed on the first line of output
and the elements of the second column are printed on the second line of output and
so on.
Solution :
PROGRAM Reading
IMPLICIT NONE
INTEGER, DIMENSION(5,4) :: TDIM
INTEGER :: ROW , COL
DO ROW = 1, 5
DO COL = 1, 4
READ(*,*)TDIM(ROW , COL)
END DO
END DO
DO COL = 1, 4
WRITE(*,*) (TDIM(ROW , COL), ROW = 1 , 5)
END DO
END PROGRAM Reading

Let us first consider the reading segment. Reading is done using two nested loops.
The outer loop index corresponds to the rows of the two-dimensional array. The
inner one corresponds to the columns. Hence, the array TDIM is read row-wise. Note
that the READ statement is executed 20 times and therefore 20 input lines are
required with one data value per line. In the printing segment, we used an implied
loop inside a DO loop.
5.6 Arrays and Subprograms
Arrays can be passed to a subprogram or can be used locally within a subprogram.
In both the cases, the array must be declared within the subprogram. The following
examples illustrate the use of one-dimensional arrays in a subprogram.
Example 1: Summation of Array Elements: Read 4 data values into an array LIST
(of size 10) and print the sum of all the elements of array LIST using a function SUM.
Solution:
110
PROGRAM Summation
IMPLICIT NONE
INTEGER, DIMENSION(10) :: LIST
INTEGER :: SUM, K
READ(*,*)(LIST(K), K = 1, 4)
WRITE(*,*) SUM(LIST, 4)
END PROGRAM Summation

INTEGER FUNCTION SUM(MARK, N)


IMPLICIT NONE
INTEGER, INTENT(IN) :: MARK(N), N
SUM = 0
DO J = 1, N
SUM = SUM + MARK(J)
END DO
END FUNCTION SUM
In this example, four elements of the array LIST are read by the READ statement.
The function SUM is called and the sum of the first four elements of array LIST is
printed. The first argument to the function is the one-dimensional array LIST. The
second argument is passed as the size of the array. In function SUM, the argument
N is used in the declaration of the array MARK. The declaration INTEGER
MARK(N) implies that the size of the array MARK is the value of N. This type of
declaration is allowed in functions and subroutines only. The elements of the array
MARK are added and the result is returned as the function value.
If the input to this program is as follows:
19, 25, 10, 82
the output would be as follows:
136
Example 2: Counting Negative Numbers within a One-Dimensional Array: Write a
subroutine FIND that takes a one-dimensional array and its size as two input
arguments. It returns the count of the negative and non-negative elements of the
array.
Solution:
SUBROUTINE FIND(A, N, COUNT1, COUNT2)
IMPLICIT NONE
INTEGER, INTENT(IN) :: N, A(N)
INTEGER, INTENT(OUT) :: COUNT1, COUNT2
INTEGER :: K
COUNT1 = 0
COUNT2 = 0
DO K = 1,N
111
IF (A(K)<0) THEN
COUNT1= COUNT1 + 1
ELSE
COUNT2= COUNT2 + 1
ENDIF
END DO
END SUBROUTINE FIND
The variable COUNT1 counts the negative numbers in the array. The variable
COUNT2 counts the non-negative integers in the array.
Programming Example:
Reversing an Array
Write a program that reverses the order of the elements of a given array. For
example, if the given array contains five elements:
35724
after reversing the order of elements, the result is
42753
Solution
! -------------------------------------------------------------
! PROGRAM Reverse:
! This program reverses the order of an input array.
! -------------------------------------------------------------

PROGRAM Reverse
IMPLICIT NONE

INTEGER, PARAMETER :: SIZE = 30 ! maximum array size


INTEGER, DIMENSION(1:SIZE) :: a ! input array
INTEGER :: n ! actual input array size
INTEGER :: Head ! pointer moving forward
INTEGER :: Tail ! pointer moving backward
INTEGER :: Temp, I

READ(*,*) n ! read in the input array


READ(*,*) (a(i), i = 1, n)
WRITE(*,*) "Input array:" ! display the input array
WRITE(*,*) (a(i), i = 1, n)

Head = 1 ! start with the beginning


Tail = n ! start with the end
DO ! for each pair...
IF (Head >= Tail) EXIT ! if Head crosses Tail, exit
Temp = a(Head) ! otherwise, swap them
a(Head) = a(Tail)
a(Tail) = Temp
Head = Head + 1 ! move forward
Tail = Tail - 1 ! move backward

112
END DO ! loop back

WRITE(*,*) ! display the result


WRITE(*,*) "Reversed array:"
WRITE(*,*) (a(i), i = 1, n)

END PROGRAM Reverse


Program Input and Output
If the input data consist of the following:
8
10 50 30 70 35 97 65 59
The out of the program is:
Input array:
10, 50, 30, 70, 35, 97, 65, 59
Reversed array:
59, 65, 97, 35, 70, 30, 50, 10

113
5.7.1 Exercises 0n dimension array
1. What is printed by the following programs?
1. program Exercises5
implicit none
INTEGER:: A(3), J
A(1) = 1
DO J = 2, 3
A(J) = 3 * A(J - 1)
END DO
WRITE(*,*) A
END Exercises5

2. program Exercises5
implicit none
INTEGER:: A(3), K
READ(*,*)A
DO K = 1,3
A(3) = A(3) + A(K)
END DO
WRITE(*,*) A(3)
END Exercises5
Assume the input for the program is:
10,20,30

3. program Exercises5
implicit none
INTEGER:: X(5), Y(5), N, K
READ(*,*)N, (X(K),Y(K),K=1,N)
DO K=X(N),Y(N)
WRITE(*,*) ('X',J=X(K),Y(K))
END DO
END Exercises5
Assume the input for the program is:
4,1,2,3,3,3,4,2,4

2. The following program segments may or may not have errors. For each one of
the segments, identify the errors(if any). Assume the following declarations :
INTEGER:: M(4)
LOGICAL:: L

a. DO K = 2,5,2
READ(*,*)M(K-1)
END DO
Assume the input for the program is:
20,40,50,30,60
b. DO K = 1,4
M(K+1) = -K
END DO

114
3. Consider the following subroutine :
SUBROUTINE CHECK(A,B,C,N)
INTEGER, INTENT(IN) :: A(10), B(5),N
INTEGER, INTENT(OUT) :: C

INTEGER ::A(10), B(5)


C = 0
DO M = 1,N
C = C + A(M)*B(M)
END DO
END SUBROUTINE CHECK

If the only declaration and assignment statement in the main program are the
following:
INTEGER ::X(5), M(10), A
A = 3
Which of the following CALL statements is correct assuming that X and M have
some value ?
A) CALL CHECK(M,X,C)
B) CALL CHECK(M(10),X(5),C,5)
C) CALL CHECK(M,X,B,A+2)
D) CALL CHECK(M,X,N,A)
E) CALL CHECK

5.7.2 Exercises - Two-Dimensional Array


1. What is printed by the following programs ?
1. program Exercises5
implicit none
INTEGER:: X(3,3), J
READ(*,*)X
WRITE(*,*) X
WRITE(*,*) (X(J,J), J = 1, 3)
WRITE(*,*) (X(J,3), J = 1, 3)
END program Exercises5

Assume the input is:


1, 5, 7
7, 5, 1
3, 8, 9

2. program Exercises5
implicit none
REAL:: B(2,3), F
INTEGER:: J, K
F(X, Y) = X + Y * 2
READ(*,*)((B(J,K), K = 1, 2), J = 1, 2)
DO J = 1, 2
B(J,3) = F(B(J,1), B(J,2))
END DO
115
WRITE(*,*) B
END program Exercises5

Assume the input is:


10, 20, 30, 40

3. program Exercises5
implicit none
INTEGER:: A(3,3) , J, K
READ(*,*)((A(K,J),K=1,3),J=1,3)
WRITE(*,*) A
WRITE(*,*) ((A(K,J),J=1,2),K=1,3)
WRITE(*,*) A(3,2)
WRITE(*,*) (A(K,2),K=3,1,-2)
END program Exercises5
Assume the input is:
1 2 3
4
5 6 7 8
9

4. program Exercises5
implicit none
INTEGER:: A(2,2) , J, K
READ(*,*)A
DO J = 1,2
WRITE(*,*) (A(J,K), K=1,2)
END DO
END program Exercises5
Assume the input is:
1 2 3 4

2. Assume the array declaration :


INTEGER:: Z(10,10)
is given. Which of the following READ statements will read the array column-
wise if the data is given one value per line ? :
I. READ(*,*)Z

II DO J = 1,10
READ(*,*)(Z(K,J),K=1,10)
END DO

III. DO K = 1,10
DO J = 1,10
READ(*,*)Z(J,K)
END DO
END DO

116
6. OUTPUT DESIGN AND FILE PROCESSING
6.1 Output Formatting
The write statement we have been using in the previous chapters is a list-directed
output statement. In list-directed output, the output list determines the precise
appearance of printed output. In other words, we have no control over the format of
the output. To control the manner in which the output is printed or to produce an
output in a more readable form, we use FORMAT statements. The general form of
a formatted WRITE statement is
WRITE(*,K) expression list
Where K : FORMAT statement label , identifies a format to be used by the print
statement. The statement number can be any positive INTEGER constant.
The format statement may be used to read or write data in a form other than the
default format, for example:
READ (*,100) i, j
WRITE (*,100) i, j
READ (*,200) x, y
WRITE (*,200) x, y
.....
100 FORMAT (2I)
200 FORMAT (2F10.6)

The general form of the FORMAT statement is


K FORMAT(specification list)
Fortran formats are used to control the appearance of the input and output. The
expression list is a list of edit descriptors, specifies the value(s) to be printed.
A FORMAT statement is a non-executable statement. It can appear anywhere in the
program before or after the associated print statement. FORTRAN provides format
specifications for blank spaces, integer, real, character and logical types. Commas
are used to separate specifications in the specification list.
The labelled FORMAT statement may be replaced by specifying the format
descriptor list as a character string directly in the WRITE or READ statement, as
follows:
READ (*,20) I, J
WRITE (*,30) X, Y
20 FORMAT( 2I )

117
30 FORMAT( 2F12.6 )
replaced by
READ (*,'(2I)') I, J
WRITE (*,'(2F12.6)') X, Y

Fortran format is to master many format edit descriptors. In the following are the
editor descriptors to be discussed.

6.2 INTEGER Output: The I Descriptor


The Iw descriptor is for INTEGER output. The general form of these descriptors
are as follows:
rIw
The meaning of r and w and I are:
• I is for INTEGER
• w is the width of field, which indicates that an integer should be printed
with w positions.
• r is the repetition indicator, which gives the number of times the edit descriptor
should be repeated. For example, 3I5 is equivalent to I5, I5, I5.
• The sign of a number also needs one position. Thus, if -234 is printed, w must be
larger than or equal to 4. The sign of a positive number is not printed.
• If a value of 12345 is printed with I3? Three positions are not enough to print the
value of five digits. In this case, traditionally, all w positions are filled with *'s.

Examples
Let us look at the following example. There are three INTEGER variables a ,
b and c with values 123, -123 and 123456, respectively. In the following table,
the WRITE statements are shown in the left and their corresponding output, all
using five positions, are shown in the right.

INTEGRAL :: a=123, b=-123, c =123456

WRITE(*,``(I5)``) a 1 2 4

WRITE(*,``(I5)``) b - 1 2 4

WRITE(*,``(I5)``) c * * * * *

118
Consider the following example.
INTEGER :: a = 3, b = -5, c = 128
WRITE(*,"(3I4)") a, b, c
The edit descriptor is 3I4 and the format is equivalent to (I4,I4,I4) . Therefore, each
of the three INTEGER variables is printed with I4. Based on the discussion earlier,
the result is the following:
3 - 5 1 2 8
Example 1: What is the minimum I specification needed to print each of the
following integers?
345, 67, -57, 1000, 123456
Solution:
Number I specification
345 I3
67 I2
-57 I3
1000 I4
123456 I6
Example 2: What will be printed by the following program?
INTEGER:: M
M = -356
WRITE(*,10) M
10 FORMAT(' ', I4)
END DO
Solution:
....+....1....+....2
-356
Notice that the carriage control character ' ' did not appear in the output. This
characters indicates that the output line is single spacing.
Example 3: If the FORMAT statement in the previous example is modified as
follows:
FORMAT(' ', I3)
What will be printed?
Solution:
....+....1....+....2....+....3.
***
119
Example 4: Assume K = -244 and M = 12. The following PRINT statements will
produce the shown outputs.
a. WRITE(*,10) K
10 FORMAT(' ', I4)

....+....1....+....2....+....3.
-244
b. WRITE(*,20) K, M
20 FORMAT(' ', I5, I6)

....+....1....+....2....+....3.
-244 12
c. WRITE(*,30) K
WRITE(*,35) M
30 FORMAT(' ', I3)
35 FORMAT(' ', I2)

....+....1....+....2....+....3
***
12

d. WRITE(*,40) K + M
40 FORMAT(' ', I5)
....+....1....+....2....+....3....+....4.
-232

INTEGER Input: The I Descriptor


Notic that
• All spaces in the w positions are removed and the result is treated as an integer.
For example, suppose we have
PROGRAM To_see
IMPLICIT NONE
INTEGER :: a, b, c, d
READ(*,"(4I5)") a, b, c, d
WRITE(*,*) a, b, c, d
END PROGRAM To_see

and the input

....+....1....+....2....+....3.
1 3 5 135 135 135
Then, all four variables receive the same value, 135.

120
Examples
Suppose we have the following input and the system ignores spaces.
....+....1....+....2....+....3.
12 34 56 78 90
• What are the values in each variable after reading in the above input?
INTEGER :: a, b, c, d
READ(*,"(I1, I2, I3, I4)") a, b, c, d

Thus, Variable a receives 1. Variable b receives 2. Variable c receives 34.


Finally, Variable d receives 56.
• What are the values in each variable after reading in the above input?
INTEGER :: a, b, c, d
READ(*,"(I3, I4, I7, I1)") a, b, c, d

Variable a receives 12. Variable b receives 34. Variable c receives 5678. Finally,
Variable d receives zero.
6.3 REAL Output: The F Descriptor
The Fw.d descriptor is for REAL output. The general form is:
rFw.d
The meaning of r, w and d are:
• F is for REAL
• w is the width of field, which indicates that a real number should be printed
with w positions.
• d indicates the number of digits after the decimal point. More precisely, of
these w positions, the right-most d positions are for the fraction part of a real
number, and the d+1 position from the right is a decimal point. The remaining w-
(d+1) positions are for the integral part. This is shown in the figure below:

• Note that the integral part contains a sign and as a result w should be greater than
or equal to d+2.
• The fractional part may have more than d digits. In this case, the (d+1)th digit
will be rounded to the dth one. For example, if 1.73 is printed with F3.1, since

121
the second digit of the fractional part is 3, the result is 1.7. However, if 1.76 is
printed with F3.1, the result becomes 1.8 because 6 is rounded.
• The fractional part may have fewer than d digits. In this case, trailing zeros will
be added.
• Note that d can be zero. In this case, no fractional part will be printed. More
precisely, the right-most position is the decimal point.
• r is the repetition indicator, which gives the number of times the edit descriptor
should be repeated. For example, 3F5.3 is equivalent to F5.3, F5.3, F5.3.
Examples
Let us look at the following example. There are two REAL variables a and b with
values 123.345 and -123.345, respectively. In the following table,
the WRITE statements are shown in the left and their corresponding output, all
using five positions, are shown in the right.
REAL:: a =123.345, b = -123.345
WRITE(*,”(F10.0)”) a 1 2 3 .
WRITE(*,”(F10.2)”) a 1 2 3 , 3 5
WRITE(*,”(F10.5)”) a 1 2 3 , 3 5 5 0 0
WRITE(*,”(F10.7)”) a * * * * * * * * * *
WRITE(*,”(F10.4)”) b - 1 2 3 , 3 5 5 0
WRITE(*,”(F10.6)”) b * * * * * * * * * *
1 2 3 4 5 6 7 8 9 10
Consider the following example. The WRITE statement has three REAL variables
and consequently the format must also have three F edit descriptors, one for each
variable.
REAL :: a = 12.34, b = -0.945, c = 100.0
WRITE(*,"(3F6.2)") a, b, c

The result is the following:


1 2 . 3 4 - 0 . 9 5 1 0 0 . 0 0

122
Example 1: What is the minimum F specification needed to print the following real
numbers?:
823.67509, 0.002, .05, -.05, -0.0008
Solution:
Number F specification
823.67509 F9.5
0.002 F5.3
.05 F3.2
-.05 F4.2
98. F3.0
98.0 F4.1
-0.0008 F7.4
Example 2: What will be printed by the following program?
program OUTPUT_F2
implicit none
REAL:: X
X = 31.286
WRITE(*,10) X
10 FORMAT(' ', F6.3)
END OUTPUT_F2
Solution: The printed output on a new page is as follows:
....+....1....+....2....+....3.
31.286
Example 3: If the FORMAT statement in the previous example is modified as
follows:
FORMAT(' ', F8.4)
What will be printed?
Solution:
....+....1....+....2....+....3.
31.2860
Example 4: If the FORMAT statement in the previous example is modified as
follows:
FORMAT(' ', F5.3)
What will be printed?
Solution:
....+....1....+....2....+....3.
*****
123
Example 5: Assume X = -366.126, Y = 6.0 and Z = 20.97. The following PRINT
statements will produce the shown outputs.
a. WRITE(*,10) X
10 FORMAT(' ', F11.5)
....+....1....+....2....+....3.
-366.12600

b. PRINT 20, X
20 FORMAT(' ', F8.3)
....+....1....+....2....+....3.
-366.126

c. WRITE(*,30) Z
WRITE(*,35) Y
30 FORMAT(' ', F4.1)
35 FORMAT(' ', F4.2)
....+....1....+....2....+....3.
21.0
6.00
d. WRITE(*,40) X / Y
40 FORMAT(' ', F7.3)
....+....1....+....2....+....3....+....4.
-61.210

REAL Input: The F Descriptors

Suppose we have the following:


REAL:: u, v, w
READ (*,"(F5.2, F5.2, F5.2)”) u, v, w
and the input is
....+....1....+....2....+....3.
1 2 5 4.5 1 9.4
Hence, u receives 1.23. Variable v receives 4.5. Variable w receives 19.4.
6.4 REAL Output: The E Descriptor
The Ew.d descriptor is for REAL output. The printed numbers will be in an
exponential form.

124
The Ew.d descriptor generates real numbers in the following form:

Of these w positions, the last three are for the exponent, including its sign, the
middle d positions are for the number in normalized form. Therefore, excluding the
exponent part, there are w-4 positions for printing the digits of the normalized
number. In fact, you can consider the normalized number is printed with Fw-4.d. The
above figure also includes a 0 and a decimal point. If the number is negative, we
must also include its sign. Hence, 4+3=7 positions are not available for printing the
normalized number and, as a result, when you use the E edit descriptor, w must be
greater than or equal to d+7; otherwise, your number may not be printed properly
and all w positions will be filled with asterisks.
Examples
In the following table, the WRITE statements use different E edit descriptors to
print the value of 3.1415926. The WRITE statements are shown in the left and
their corresponding output, all using 12 positions, are shown.
REAL :: PI=3.1415926
WRITE(*,10) PI
10 FORMAT (E12.5)

Output
0 . 3 1 4 1 6 E + 0 1
1 2 3 4 5 6 7 8 9 10 11 12
The following table shows some examples of real numbers and their presentation in
FORTRAN:
Real Decimal Notation FORTRAN Representation
Number
6.3 x 10-5 0.000063 0.63E-04
4.932 x 107 49320000.0 0.4932E+08
-5.7 x 10-6 -0.0000057 -0.57E-05
5.7 x 10-6 0.0000057 0.57E-05
5.7 x 106 5700000.0 0.57E+07

125
REAL Input: E Descriptors
Suppose we have the following:
REAL :: u
READ(*,"(F10.4)") u
and the input is
....+....1....+....2....+....3.
12345E20
then u takes the first ten positions. The exponent is 20 and 12345 is read in with 4
digits in the fractional part. Therefore, the actual value read in is 1.2345×1020.
Examples
Suppose we have the following input and the system.
....+....1....+....2....+....3.
12 3.4 56E 78. 90
What are the values in each variable after reading in the above input?
REAL :: a, b, c, d
READ(*,"(F3.0, F4.1, F6.2, F7.3)") a, b, c, d

Variable a read in is 12.0. Variable b receives 3.4. Variable c receives 0.56×107.


Variable d takes receives 8.9
• What are the values in each variable after reading in the above input?
REAL :: a, b, c, d
READ(*,"(F6.1, F3.2, F5.0, F6.1)") a, b, c, d

Variable a receives 123.4. Variable b receives 0.05. Variable c receives 6×1078.


Finally, d receives 0.9.

6.5 LOGICAL Output: The L Descriptor

The Lw descriptor is for LOGICAL output. While Fortran uses


.TRUE. and .FALSE. to indicate logical values true and false, respectively, the
output only show T and F. The general form of this descriptor is as follows:
rLw
The meaning of r and w are:
• L is for LOGICAL
• w is the width of field, which indicates that a logical value should be printed
with w positions.

126
• The output of a LOGICAL value is either T for .TRUE. or F for .FALSE. The
single character value is shown in the right-most position and the remaining w-
1 positions are filled with spaces. The is shown in the figure below.

• r is the repetition indicator.


Example 1:
Let us look at the following example. There are
two LOGICAL variables a and b with values .TRUE. and .FALSE., respectively.
In the following table, the WRITE statements are shown in the left and their
corresponding output are shown in the right.

LOGICAL:: a = TRUE. , b =.FALSE.


WRITE(*,”(L1, L2)”) a , b T F
WRITE(*,”(L3, L4”) a , b T F
1 2 3 4 5 6 7
• The first WRITE uses L1 and L2 to print .TRUE. and .FALSE., respectively.
Therefore, a T is shown in position one (L1) and a F is shown in position three
(L2).
• The second WRITE uses L3 and L4 to print .TRUE. and .FALSE.. Therefore,
a T is printed in the third position of the first three positions, and a F is printed in
the fourth position of the next four positions. There are seven positions used in
total.
Example 2: What will be printed by the following program?
PROGRAM WRITE_L_2
IMPLICIT NONE
LOGICAL:: X, Y
X = .TRUE.
Y = .FALSE.
WRITE(*,“(L1, 2X, L5)”)X, X
WRITE(*,(*,“(L1, 2X, L7)”)Y, Y
20 FORMAT(L1, 2X, L7)
END PROGRAM WRITE_L_2
127
Solution:
....+....1....+....2....+....3.
T T
F F
LOGICAL Input: The L Descriptor
Consider the following example:
LOGICAL :: a, b, c
READ(*,"(L3, L8, L10)") a, b, c
Suppose the input is the following:
....+....1....+....2....+....3.
Fax Trust Thursday

Variable a takes the first three positions, which contain F, a and x.


Thus, a receives .FALSE. since the first character is a F. Variable b takes the next
8 positions, which contain two spaces, T, r, u, s, t and a space. Since the first non-
blank character is a T, b receives .TRUE. Variable c takes the next 10 positions,
which contain two spaces, T, h, u, r, s, d, a and y. Therefore, c also receives .TRUE.

6.6 CHARACTER Output: The A Descriptor


The A and Aw descriptors are for CHARACTER output. The general form of
these descriptors are as follows:
rA and rAw
The meaning of r and w are:
• A is for CHARACTER
• w is the width of field, which indicates that a character string should be printed
with w positions.
• The output of the character string depends on two factors, namely the length of
the character string and the value of w. Here are the rules:
o If w is larger than the length of the character string, all characters of the
string can be printed and are right-justified. Also, leading spaces will be
added. The following example prints the string "12345" of length 5 (i.e., five
characters) using A6.
WRITE(*,'(A6)') "12345"

128
Since w is larger than the length of the string, all five characters are printed and
right-justified. The result is shown below:
1 2 3 4 5

o If w is less than the length of the character string, then the string
is truncated and only the left-most w positions are printed in
the w positions. The following example prints the string "12345678" of length
8 (i.e., eight characters) using A6.
WRITE(*,'(A6)') "12345678"
Since w is less than the length of the string, only the first six characters are
printed. The result is shown below:
1 2 3 4 5 6

o If w is equal to the length of the character string, then it is an exact match. All
characters can be printed and all w positions are filled.
o If w is missing, then the value of w is assumed to be the length of the
string. The following example shows two WRITE statements. The first one
uses A to print a, a string of length 5. The second one also uses A to print b, a
string of length 2.
CHARACTER(LEN=5) :: a = "abcde"
CHARACTER(LEN=2) :: b = "MI"

WRITE(*,'(A)') a
WRITE(*,'(A)') b

Since the A edit descriptor will use the length of the string as the value of w, the
above is equivalent to the following:
CHARACTER(LEN=5) :: a = "abcde"
CHARACTER(LEN=2) :: b = "MI"

WRITE(*,'(A5)') a
WRITE(*,'(A2)') b
Therefore, the A edit descriptor is more convenient than Aw.
• r is the repetition indicator, which gives the number of times the edit descriptor
should be repeated. For example, 3A5 is equivalent to A5, A5, A5, and 3A is
equivalent to A, A, A.
129
• Please keep in mind that the length of the string includes trailing spaces. For
example, if we have the following:
CHARACTER(LEN=5) :: a = "123"
CHARACTER :: b = "*"

WRITE(*,"(A,A)") a, b
it is equivalent to
CHARACTER(LEN=5) :: a = "123"
CHARACTER :: b = "*"

WRITE(*,"(A5,A1)") a, b

and the result is


1 2 3 *

Example 1:
Let us look at the following example.
CHARACTER(LEN=5) :: a = "12345"
CHARACTER :: b = "*"

In the following table, the WRITE statements are shown at the left and their
corresponding output are shown at the right.

a =”12345” b =”*”
WRITE(*,”(A1, A)”) a, b 1 *
WRITE(*,”(A2, A)”) a, b 1 2 *
WRITE(*,”(A3, A)”) a, b 1 2 3 *
WRITE(*,”(A4, A)”) a, b 1 2 3 4 *
WRITE(*,”(A5, A)”) a, b 1 2 3 4 5 *
WRITE(*,”(A6, A)”) a, b 1 2 3 4 5 *
WRITE(*,”(A7, A)”) a, 1 2 3 4 5 *
WRITE(*,”(A, A)”) a, 1 2 3 4 5 *
1 2 3 4 5 6 7 8

Example 2: What will be printed by the following program?

PROGRAM WRITE_L_E2
IMPLICIT NONE
CHARACTER :: TEXT*5 TEXT = 'KFUPM'
130
WRITE (*,”(A, 3X, A3, 3X, A9)”) TEXT, TEXT, TEXT
END PROGRAM WRITE_L_E2
Solution:
....+....1....+....2....+....3....+....4.
KFUPM KFU KFUPM

CHARACTER Input: The A Descriptor


Example 1:
Suppose we have the following input and the system ignores spaces.
....+....1....+....2....+....3....+....4.
ABCDEFGHIJKLMNOPQRST
• What are the values in each variable after reading in the above input?
CHARACTER(LEN=5) :: a, b, c
CHARACTER(LEN=3) :: d

READ(*,"(A4, A5, A7, A") a, b, c, d

Variable a receives "ABCD ". Variable b receives "EFGHI".


Variable c receives "LMNOP". Finally, variable d receives "QRS".
• What are the values in each variable after reading in the above input?
CHARACTER(LEN=5) :: a, b*3, c*7, d*4
INTEGER :: a, b, c, d

READ(*,"(4A5)") a, b, c, d

Variable a receives "ABCDE". Variable b receives "HIJ".


Variable c receives "KLMNO " and the variable d receives "QRST".
6.7 Print Control : Scanning a Format:
How about the following example? INTEGER variable Age is printed
using I4, CHARACTER variable State is printed using F10.2. This is a mistake,
because CHARACTER variables must be printed with the A edit descriptor and
because the F descriptor can only print REAL values. Consequently, if you run this
program, you will get a run time error when this WRITE is executed.
CHARACTER(LEN=8) :: State = "Michigan"
INTEGER :: Age = 30
REAL :: Salary = 32165.99
LOGICAL :: InState = .TRUE.

WRITE(*,"(I4, F10.2, A, L2)") Age, State, Salary, InState


131
What If the Numbers of Variables and Edit Descriptors Are not Equal?
We have two cases to consider:
• The number of variables is less than the number of edit descriptors. This is
shown with the following example:
INTEGER :: a = 1, b = 2, c = 4
CHARACTER(LEN=20) :: FMT = "(6I5)"
WRITE(*,FMT) a, b, c

This example has three variables and six edit descriptors in the format. This is a
simple case. Here is the answer:
variables a, b and c are printed with I5, I5 and I5. The three unused I5s are
ignored.
• The number of variables is greater than the number of edit descriptors. This is
shown with the following example:
INTEGER :: a = 1, b = 2, c = 3, d = 5, e = 8
CHARACTER(LEN=20) :: FMT = "(I4, I3)"
WRITE(*,FMT) a, b, c, d, e

This example has five variables; but the format to print them has only two edit
descriptors.
Examples
• The following has an array x with maximum number of elements 100. But, the
actual number of elements in x depends on the input. The WRITE statement
always prints the elements of x five elements per row.
INTEGER, DIMENSION(1:100) :: x
INTEGER :: n
INTEGER :: i

READ(*,*) n, (x(i), i=1, n)

WRITE(*,"(5E17.7)") (x(i), i = 1, n)

The format has five E17.7s. Therefore, after x(1) to x(5) are printed, x(6) to x(10)
are printed on the second line, followed by x(11) to x(15) on the third line and so on
until all n elements of x are printed.
• How about the follow example, which is a slightly modified version of the above.
INTEGER, DIMENSION(1:100) :: x
INTEGER :: n
132
INTEGER :: i

READ(*,*) n, (x(i), i=1, n)


WRITE(*,"(I5, E17.7)") (i, x(i), i = 1, n)

• Note that the program below prints the same output; but it uses a DO-END DO.
Obviously, the version above is shorter.
INTEGER, DIMENSION(1:100) :: x
INTEGER :: n
INTEGER :: i

READ(*,*) n, (x(i), i=1, n)


DO i = 1, n
WRITE(*,"(I5, E17.7)") i, x(i)
END DO

Programming Example:
Write a program that for each INTEGER in the range of 1 and 5, prints its value,
square, cube and square root.
Solution
PROGRAM Squares_and_Roots
IMPLICIT NONE
INTEGER, PARAMETER :: MAXIMUM = 5
INTEGER :: i
CHARACTER(LEN=30) :: Format

Format = "(3I6, F12.7)"


DO i = 1, MAXIMUM
WRITE(*,Format) i, i*i, i*i*i, SQRT(REAL(i))
END DO
END PROGRAM Squares_and_Roots

Program Input and Output


The output of the program is:
....+....1....+....2....+....3.
1 1 1 1.0000000
2 4 8 1.4142135
3 9 27 1.7320508
4 16 64 2.0000000
5 25 125 2.2360680

6.7.1 Horizontal Position Control : Horizontal Spacing: nX


To skip the next n positions, use the X edit descriptor. The general form of this
descriptor is as follows:
133
nX
• The next n positions are skipped (blanks) . The X edit descriptor can be used
for both input and output. For output, the next n positions are skipped and the
content there is unchanged. For input, it simply skips the n positions.
• The X edit descriptor is only for skipping positions and does not read and write
any values.
Example 1:
Consider the following input:
....+....1....+....2....+....3....+....4.
123 456 789 012
Suppose this input is read by the following READ statement.
INTEGER :: a
REAL :: b
CHARACTER(LEN=4) :: c
READ(*,"(2X ,I4,3X,F5.2,2X,A)") a, b, c

1 2 3 4 5 6 7 8 0 1 2
2x I4 3X F5.2 2X A4

a receives 3 . variable c receives 0.78. Finally variable c receives


characters " 012".
• Consider the following WRITE statement:
CHARACTER(LEN=30) :: FMT = "(1X,I3,3X,I5,2X,F5.2)"
INTEGER :: a = 12
INTEGER :: b = 768
REAL :: c = 3.715

READ(*,FMT) a, b, c
It should generate the following output:

Example 2: The following program:


PROGRAM Horizontal_Xex1
IMPLICIT NONE
REAL:: A, B
A = -3.62
B = 12.5
WRITE(*,5 )A, B
5 FORMAT(' ', F5.2, F4.1)
END Horizontal_Xex1

134
prints the following output:
....+....1....+....2....+....3....+....4.
-3.6212.5
The output is not readable because the two printed values are not separated by blanks.
If we modify the format statement using X specification as follows:
FORMAT(' ', F5.2, 3X, F4.1)
the output becomes:
....+....1....+....2....+....3....+....4.
-3.62 12.5
The X specification can be used as a carriage control character. The following pairs
of FORMAT statements print the same output.
10 FORMAT(' ', I2)
is equivalent to
10 FORMAT(1X, I2)
and
20 FORMAT(' ', 2X, F4.1)
is equivalent to
20 FORMAT(3X, F4.1)

6.7.2 Vertical Position Control : The Slash Edit Descriptor: /

The slash edit descriptor / is used to terminate the current input/output line. The
general forms of this descriptor are as follows:
/ and r/
• For Input: The current input line is skipped and the remaining unread content on
the current input line is ignored. The reading process starts at the first position on
the next input line.
• For Output: The current output line is printed and the next output item, including
the printer control character, starts at the first position of a new buffer output line.
• While commas are used for separating two neighboring edit descriptors, they are
not required if one of these two neighboring edit descriptors is a /. For example,
the following
READ(*,"(I3,5X,I5,/,/,T15,F10.0)") ......
135
is equivalent to
READ(*,"(I3,5X,I5//T15,F10.0)") ......
r is equivalent to writing / r times. For example, 4/ is equivalent to ////.

Examples
Consider the following input:
....+....1....+....2....+....3....+....4.
123 456
789 012
345 678
Suppose this input is read by the following READ statement.
INTEGER :: a, b, c
READ(*,"(I5/I5/I5)") a, b, c

The reading starts with the first input line. Thus, a receives a value of 123. Since the
next edit descriptor is a /, the content on the current input line is ignored. As a result,
, the value for b receives 789. After this, we see a second / which causes ignoring
the remaining of the second input line. Therefore, the value for c receives 345.
Consider the following input:
....+....1....+....2....+....3....+....4.
123 456
789 012
345 678
901 234
567 890
135
Suppose this input is read by the following READ statement.

INTEGER :: a, b, c, d

READ(*,"(I5//I5/I5/)") a, b, c
READ(*,"(I5)") d

a is receives 123. b receives 345 from the third input line. After reading b, we have
a / and c will use the fourth input line. Hence, c receives 901. The sixth input line is
read and d receives 135.
The above discussion is illustrated with the figure below.

136
6.7.3 Grouping: r( )
Sometimes we want to repeat several edit descriptors rather than a single one. In
this case, you can group several edit descriptors together using ( ). This grouping
descriptor has the following general forms:
r( ) and ()
The meaning of r( ) and ( ) are:
• For the form of r(....), the edit descriptors within () repeat r times. For example,
(1X, 3(I5, F5.2), A)
is equivalent to the following:
(1X, I5, F5.2, I5, F5.2, I5, F5.2, A)
• Grouping can also be nested. Suppose we have the following
(1X, 3(I5, 2(I4, A3)), A)
Then, we can expand 3(...) into the following:
(1X, I5, 2(I4, A3), I5, 2(I4, A3), I5, 2(I4, A3), A)
After expanding all 2(...)'s, we have the final equivalent format:
(1X, I5, I4, A3, I4, A3, I5, I4, A3, I4, A3, I5, I4, A3, I4, A3, A)
Examples:
The following pairs of FORMAT statements illustrate the use of repetition
constants:
WRITE(*,”(3X, I2, 3X, I2)”)
is equivalent to
WRITE(*,”(2(3X, I2)”)
and

137
WRITE(*,”(F5.1,F5.1,F5.1,5X,I3,5X,I3,5X,I3,5X,I3)”)
is equivalent to
WRITE(*,”(3F5.1,4(5X, I3)”)

6.8 File Processing


In many applications, the amount of data read and/ or produced is huge. Providing
data interactively is not efficient, thus a different way to handle data is needed,
namely, files. Another reason for using files comes from the repetitive use of the
same data every time the program is run; making the data entry task very tedious.
The third reason is that data in many real applications is taken or recorded by
instruments or devices then used for analysis and computations.

6.8.1 Opening Files


Before using a file for input or output, it must be prepared for that operation. Files
that are used for input must exist prior to their usage. To prepare a file for input, the
following OPEN statement must precede any read statement from that file:
OPEN(UNIT=INTEGER EXPR,FILE= 'FILENAME', STATUS = 'OLD')
where UNIT equals an integer expression in the range of 0 to 99. Avoid using 5 and
6 as unit numbers since they are already assigned for the keyboard and the screen.
The filename is a character string containing the actual name of the file followed by
the file extension. In the IBM mainframe, the file name is separated from the file
extension by a space and if the extension is omitted, it is assumed to be FILE. Upon
opening a file for reading, the reading will take place from the beginning of the file.
Files that are used for output may not exist before being used. If the file does not
exist, it will be created whereas if it exists its contents will be erased. To prepare a
file for output, the following statement must precede any write statement to that file:
OPEN(UNIT =INTEGER EXPR, FILE= 'FILENAME',STATUS = 'NEW')
or
OPEN(UNIT=INTEGER EXPR,FILE='FILENAME',STATUS ='UNKNOWN')
The second statement is preferred in our system because the first one assumes that
the file does not exist and, therefore, if it exists an error occurs.
Example 1: Assume that you want to use file POINTS DATA as an input file. The
following statement will then appear before any read statement from the file:

138
OPEN(UNIT = 1, FILE = 'POINTS DATA', STATUS = 'OLD')
Example 2: Assume that you want to use file RESULT DATA as an output file. The
following statement will then appear before any write statement to the file:
OPEN(UNIT = 1, FILE = 'RESULT DATA',STATUS = 'UNKNOWN')

6.8.2 Reading from Files


To read from a file, the file must have been opened. The READ statement will be in
the following form:
READ(UNIT, *) VARIABLE LIST
where UNIT is the same value that is used in the open statement. The rules of reading
are exactly the same as the ones you have already seen, the only difference being
that data is taken from the file.
Example 1: Find the sum of three exam grades taken from file EXAM DATA.
Solution:
PROGRAM OPEN_FILE
IMPLICIT NONE
INTEGER:: EXAM1, EXAM2, EXAM3, SUM
OPEN(UNIT = 10, FILE = 'EXAM DATA', STATUS = 'OLD')
READ(10, *) EXAM1, EXAM2, EXAM3
SUM = EXAM1 + EXAM2 + EXAM3
WRITE(*,*) SUM
PROGRAM OPEN_FILE
In many cases, the number of data values in a file is not known and we would like to
do some calculations on the data values the file contains. For these cases, the read
statement will look as follows:
READ(UNIT, *, END = NUMBER) VARIABLE LIST
where number is the label of the statement where control will be transferred after
all the data from the file is read.
Example 2: Find the average of real numbers that are stored in file NUMS DATA.
Assume that we do not know how many values are in the file and that every value is
stored on a separate line.
Solution:
PROGRAM OPEN_FILE
IMPLICIT NONE
REAL:: NUM, SUM, AVG
INTEGER:: COUNT
OPEN(UNIT = 12, FILE = 'NUMS DATA', STATUS = 'OLD')
SUM = 0.0

139
COUNT = 0
333 READ(12, *, END = 999) NUM
SUM = SUM + NUM
COUNT = COUNT + 1
GOTO 333
999 AVG = SUM / COUNT
WRITE(*,*) AVG
PROGRAM OPEN_FILE
6.8.3 Writing to Files
To write to a file, the file must have been opened using an OPEN statement and the
WRITE statement must be used in the following form:
WRITE(UNIT, *) EXPRESSION LIST
where UNIT is the same value that is used in the OPEN statement. The rules of
writing to a file are exactly the same as those of the print statement. The * in the
WRITE statement indicates that the output is free formatted. If format is needed, the
format statement number is used instead.
Example: Create an output file CUBES DATA that contains the table of the cubes
of integers from 1 to 20 inclusive.
Solution:
PROGRAM OPEN_FILE
IMPLICIT NONE
INTEGER:: NUM
OPEN(UNIT =20, FILE ='CUBES DATA',STATUS = 'UNKNOWN')
DO NUM = 1, 20
WRITE(20, *) NUM, NUM**3
END DO
PROGRAM OPEN_FILE

Format statement could be used with the write statement in the same way it is used
with the print statement. The * in the write statement is replaced with the format
statement number.

140
6.9 Exercises
1. What will be printed by each of the following programs?
1. PROGRAM EX_FILE
IMPLICIT NONE

REAL ::X
X = 123.8367
WRITE(*,”(F7.2, 2X, F6.2, F9.5) “)X, X, X
END PROGRAM EX_FILE

2. PROGRAM EX_FILE
IMPLICIT NONE
INTEGER:: J, K, N
K = 123
J = 456
N = 789
WRITE(*,”(I3) “)K
WRITE(*,”(3X,I3) “)J
WRITE(*,”(6X,I3) “)N
END PROGRAM EX_FILE

3. WRITE(*,20)-35, 0.0, 12 * 10.0, 125 / 5


20 FORMAT(1X,I3,'+',F3.1,'IS NOT EQUAL',F6.1,'-',I2)
END

4. PROGRAM EX_FILE
IMPLICIT NONE
INTEGER:: ARR(5), K
READ(*,*)( ARR(K), K = 1, 5)
DO K = 1, 5
WRITE(*,”(I4)”)ARR(K)
END DO
END PROGRAM EX_FILE
Assume the input for the above program is:
10 20 30 40 50

2. Complete the following programs in order to get the required outputs:


1. REAL X
X = 5.98
WRITE (*,1) X
WRITE (*.2) X
1 FORMAT( )
2 FORMAT( )
END
The required output is:
....+....1....+....2....+....3....+....4.
141
X=5.980 X=6.0
2. IMPLICIT NONE
INTEGER:: B
REAL:: A, C
A = 3.1
B = 12.5
C = 127.66
WRITE(*,20)A, B, C
20 FORMAT( )
END
The required output is:
....+....1....+....2....+....3....+....4.
3.10 12 127.7

3. Consider the following program


IMPLICIT NONE
INTEGER:: X
REAL:: Y
X = 469
Y = 17.38
WRITE(*,2) X, Y
2 FORMAT( )
END

Given the following format statements below:


a. 2 FORMAT(5X, I3, 2X, F4.1)
b. 2 FORMAT(6X, I3, 2X, F4.1)
c. 2 FORMAT(1X, I8, F6.1)

Which of the above FORMAT statements can be used in place of the FORMAT
statement in the program to print the output as follows?
....+....1....+....2....+....3....+....4.
469 17.4

4. Which of the following statements is/are FALSE about files:


1. The statement that assigns unit number 9 to the input file "DATA" is:
OPEN (UNIT = 9, FILE = 'DATA',STATUS = 'OLD')
2. The OPEN statement for a data file must precede any READ or
WRITE statements that uses that file.
3. A statement that writes two numbers into a file may look like:
WRITE(9, *) K, L
4 A file is a collection of data records.
5. A file is usually used only once.
6. A file can be opened at the same time with two different unit
numbers.

142
5. What will be printed by the following programs?
1. IMPLICIT NONE
INTEGER:: M, K
OPEN(UNIT = 10,FILE ='INPUT DATA',STATUS='OLD')
READ(10,*) ( M, K = 1,100)
10 WRITE(*,*) M, K-1
END

Assume that the file 'INPUT DATA' contains the following:


1 2 3
4 5
6 7 8 9
6

2. IMPLICIT NONE
INTEGER:: J, K
OPEN (UNIT = 3, FILE = 'FF1',STATUS = 'OLD')
DO J=1,100
READ ( 3,*,END = 60) K
END DO
WRITE(*,*) 'THE VALUES ARE:'
WRITE(*,*) K,J
END
The contents of the file 'FF1' are:
20 50 67 45 18 -2 -20
88 66 77 105 55 300

143

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy