ZetCode

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.

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

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

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

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

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

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

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

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

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

grade.f90
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: IF construct

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

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Fortran tutorials.