Fortran conditionals
last modified November 14, 2026
A conditional chooses which statements run, based on a logical expression. The
condition must be a logical value: Fortran does not treat zero as
false and a non-zero number as true, so a bare if (n) does not
compile. Apart from that restriction, the language has the usual toolkit: an
if statement, an if construct with
else if and else branches, and
select case for choosing among many values.
The if statement
The simplest form is the if statement, which runs a single
statement when the condition is true. It has no then and no
end if, and it must fit on one line. As soon as more than one
statement is needed, the block form with then and
end if begins. Both forms are shown below.
program ifdemo
implicit none
integer :: temperature
temperature = 31
if (temperature > 30) print *, 'It is hot'
if (temperature > 30) then
print *, 'It is hot'
print *, 'Drink water'
end if
end program ifdemo
The variable holds 31, so the condition is true and the output has three lines:
one from the one-line form and two from the block. The block is the ordinary
form in modern code; the one-line statement is used for a short action such as
a print or a stop. The block form uses
if ... then and end if, and end if may
also be written as one word, endif.
$ gfortran if1.f90 -o if1 $ ./if1 It is hot It is hot Drink water
if and else
The else branch runs when the condition is false. Exactly one of
the two branches executes, so a program can choose between two actions without
repeating the condition. The condition here calls the intrinsic function
mod, which is the usual way to test divisibility.
program ifelse
implicit none
integer :: n
n = 17
if (mod(n, 2) == 0) then
print *, n, 'is even'
else
print *, n, 'is odd'
end if
end program ifelse
Since 17 is odd, the remainder of the division by 2 is 1 and the condition is
false, so the else branch prints the message. The comparison
== between two integers produces a logical value,
which is exactly what if expects. Written with the
modulo function the program would behave the same for positive
numbers.
$ gfortran ifelse.f90 -o ifelse
$ ./ifelse
17 is odd
else if chains
Several mutually exclusive cases are written as a chain of
else if branches. The conditions are tested from the top, and the
first true one wins, so their order matters. The final else is
optional; without it nothing happens when every condition is false.
program elseif
implicit none
integer :: score
score = 83
if (score >= 90) then
print *, 'grade A'
else if (score >= 80) then
print *, 'grade B'
else if (score >= 70) then
print *, 'grade C'
else
print *, 'grade F'
end if
end program elseif
The score 83 fails the first test and passes the second, so the program prints
grade B and never looks at the third condition. Because the first
branch already caught every score of 90 and above, the second condition does
not need an upper bound. The spelling elseif without the blank is
also accepted.
$ gfortran elseif.f90 -o elseif $ ./elseif grade B
Nested if constructs
An if construct may contain another one. Each
end if closes the nearest open construct, so the indentation is
what makes the structure readable. A condition that needs both parts to hold
can often be flattened with .and., which removes one level of
nesting.
program nest
implicit none
integer :: x, y
x = 5
y = 12
if (x > 0) then
if (y > 10) then
print *, 'both conditions hold'
else
print *, 'only x is positive'
end if
else
print *, 'x is not positive'
end if
end program nest
Both variables have the expected values, so the innermost branch runs. The
inner else belongs to the inner if, which the
indentation shows clearly. Replacing the two tests with
if (x > 0 .and. y > 10) then would give the same output for
this input, but would lose the ability to distinguish the two failure cases.
$ gfortran nest.f90 -o nest $ ./nest both conditions hold
Named if constructs
A construct may carry a name, written after the keyword and repeated after
end if. The name is not required for a simple
if, but it becomes valuable in a long procedure with several
nested constructs, where it documents which end if closes which
if. A name is required on a do construct that an
exit statement leaves, but on an if construct it is
only documentation for the reader.
program named
implicit none
integer :: a, b
a = 10
b = 0
outer: if (b /= 0) then
print *, a / b
else outer
print *, 'division by zero avoided'
end if outer
end program named
The construct is called outer, and the name appears three times:
after if, after else, and after end if.
The divisor is zero, so the condition is false and the else
branch runs instead of the division. Without the guard the division by zero
would stop the program with a runtime error.
$ gfortran named.f90 -o named $ ./named division by zero avoided
select case
When one value is compared against a list of possibilities,
select case is clearer than a chain of else if
branches. The selector goes in parentheses after select case, and
each case lists one or more values. The selector must be an
integer, a character, or a logical value; reals are not allowed, because
equality between reals is unreliable.
program selcase
implicit none
integer :: choice
choice = 2
select case (choice)
case (1)
print *, 'one'
case (2)
print *, 'two'
case (3:5)
print *, 'three to five'
case default
print *, 'something else'
end select
end program selcase
The selector is 2, which matches the second case, so the program prints
two. The third case uses a range, written with a colon, and
matches 3, 4 and 5. case default catches every value that no
other case matched; it must be the last case, and it is optional. The cases
must not overlap, and the compiler reports an error if they do, so at most one
of them can ever match a given value.
$ gfortran selcase.f90 -o selcase $ ./selcase two
Case ranges and open ends
A range may omit its lower or its upper bound. case (90:) matches
every value from 90 upward, and case (:0) matches everything up to
zero. This makes select case a good fit for a grading table, where
the ranges are naturally open at one end.
program selrange
implicit none
integer :: score
score = 85
select case (score)
case (90:)
print *, 'A'
case (80:89)
print *, 'B'
case (70:79)
print *, 'C'
case (60:69)
print *, 'D'
case default
print *, 'F'
end select
end program selrange
The score 85 falls into the range 80 to 89, so the second case prints
B. The first case has no upper bound, so it catches every score
of 90 and above, including values above 100. case default
therefore catches only the scores below 60. The ranges must not overlap, and
the compiler reports an error if they do.
$ gfortran selrange.f90 -o selrange $ ./selrange B
select case with characters
A character selector is compared with the case labels using the
same blank padding rules as ==. Several values in one
case are separated by commas, which is the usual way to accept
synonyms of a command. Because the selector here is a fixed-length string, a
shorter input is padded with blanks before the comparison.
program selchar
implicit none
character(len=10) :: command
command = 'start'
select case (command)
case ('start', 'run')
print *, 'starting'
case ('stop', 'quit')
print *, 'stopping'
case default
print *, 'unknown command: ', trim(command)
end select
end program selchar
The value start is stored in a string of length 10 and padded with
five blanks, and the label 'start' has length 5, so the two match
after padding. The output confirms the first case. A value that matches
nothing falls into case default, where trim removes
the padding before printing.
$ gfortran selchar.f90 -o selchar $ ./selchar starting
The merge function
Sometimes a program needs a value chosen by a condition rather than a branch.
The intrinsic function merge(tsource, fsource, mask) returns its
first argument when the mask is true and its second when it is false. Both
arguments are evaluated, so it is not a replacement for an
if whose branches have side effects, but it works element by
element on arrays and can be used inside an expression.
program merge1
implicit none
integer :: a, b, m
real :: x
a = 12
b = 7
m = merge(a, b, a > b)
print *, m
x = -3.5
print *, merge(x, -x, x >= 0.0)
print *, merge('yes', 'no ', m == 12)
end program merge1
The first call returns a, because 12 is greater than 7. The second
returns the negative of a negative number, which is the absolute value, and it
prints 3.5. The third chooses between two strings and prints yes,
since m is 12. The two character arguments have the same length,
which keeps the result the same length as well.
$ gfortran merge1.f90 -o merge1
$ ./merge1
12
3.50000000
yes
A complete example
The program below validates its input and then classifies it. The validation
uses a compound condition with .or., and the classification is a
chain of else if branches that assigns a letter. The output uses
the i0 edit descriptor, which prints an integer without leading
blanks.
program grade
implicit none
integer :: score
character(len=1) :: letter
score = 78
if (score < 0 .or. score > 100) then
print *, 'invalid score'
stop
end if
if (score >= 90) then
letter = 'A'
else if (score >= 80) then
letter = 'B'
else if (score >= 70) then
letter = 'C'
else
letter = 'F'
end if
print '(a, i0, a, a)', 'score ', score, ' gets ', letter
end program grade
The first construct rejects a score outside the range and stops the program
before the rest runs. The second construct assigns one of four letters, and
because 78 is below 80 and not below 70, it gets C. The
stop statement takes an optional integer code, which is useful in
a program that a script runs.
$ gfortran grade.f90 -o grade $ ./grade score 78 gets C
Next steps
Fortran loops shows the constructs that repeat a
block, and the relational and logical operators used in these conditions are
described in Fortran operators and
expressions. The intrinsic numeric
functions article covers the comparison helpers such as
max, min and sign.
Source
GNU Fortran: SELECT CASE construct
Fortran 2018 standard (J3/18-007r1)
In this article we have branched with the one-line if and the
if construct, chained conditions with else if, nested
and named constructs, chosen among values with select case
including open ranges and character labels, and selected values with
merge. The previous article,
Fortran operators and expressions, describes
the conditions themselves.
Author
List all Fortran tutorials.