Fortran operators and expressions
last modified November 14, 2026
An expression combines values and operators into a new value, such as
2 + 3 * 4 or a > b .and. c < 10. Fortran has
the arithmetic, relational, and logical operators of most languages, but the
details matter: integer division truncates, the remainder has two different
functions, and the precedence of ** against a minus sign catches
people who arrive from C. This article goes through the operators one group at
a time and finishes with a complete program that uses most of them.
Arithmetic operators
The five arithmetic operators are +, -,
*, / and **. The first four work as in
other languages; ** raises a number to a power, and it replaces
the pow function of C. A sign in front of a value is a unary
operator, so -a is an expression. All of them accept integers,
reals, and complex numbers, and the result has the type of the operands after
any necessary conversion.
program arithmetic
implicit none
integer :: a, b
a = 7
b = 3
print *, 'a + b =', a + b
print *, 'a - b =', a - b
print *, 'a * b =', a * b
print *, 'a / b =', a / b
print *, 'a ** b =', a ** b
end program arithmetic
The program prints one result per line. The sum, difference and product are what one expects; the division gives 2 and not 2.333, and the exponentiation computes 7 to the power of 3. The labels in the output are printed by the same statement, which is convenient in a program whose purpose is to show values.
$ gfortran arith.f90 -o arith $ ./arith a + b = 10 a - b = 4 a * b = 21 a / b = 2 a ** b = 343
Integer division truncates toward zero
When both operands of / are integers, the result is an integer and
the fractional part is discarded. The direction of the truncation is toward
zero, not toward minus infinity, so -7 / 3 is -2 and
-7 / (-3) is 2. The remainder of the division is not lost: it can
be recovered with the expression used in the second line, which subtracts the
product of the quotient and the divisor from the dividend.
program divtrunc
implicit none
integer :: a, b
a = 7
b = 3
print *, a / b, -a / b, a / (-b), (-a) / (-b)
print *, 'remainder:', a - (a / b) * b
end program divtrunc
All four divisions truncate toward zero, so the results are 2, -2, -2 and 2.
The remainder is 1, which agrees with the identity
a = (a / b) * b + remainder. The parentheses around
-a and -b are not required, since the unary minus
binds tighter than the division; they make the intention clear.
$ gfortran divtrunc.f90 -o divtrunc
$ ./divtrunc
2 -2 -2 2
remainder: 1
Remainders with mod and modulo
The remainder of an integer division is computed by two intrinsic functions
that differ only in the sign of the result. mod(a, b) takes the
sign of the dividend a, like the % operator in C,
while modulo(a, b) takes the sign of the divisor b.
The two agree when both arguments are positive, which is why the difference is
easy to miss.
program modvs
implicit none
integer :: a, b
a = 7
b = 3
print *, 'mod(7, 3) =', mod(a, b)
print *, 'mod(-7, 3) =', mod(-a, b)
print *, 'mod(7, -3) =', mod(a, -b)
print *, 'modulo(-7, 3) =', modulo(-a, b)
print *, 'modulo(7, -3) =', modulo(a, -b)
end program modvs
With a positive dividend both functions return 1. With a negative dividend
mod returns -1, because it keeps the sign of the dividend, while
modulo returns 2, because it chooses the representative with the
sign of the divisor. The function to use depends on the problem: converting an
angle to the range 0 to 360 degrees needs modulo, and testing
whether a number is even needs either one.
$ gfortran modvs.f90 -o modvs $ ./modvs mod(7, 3) = 1 mod(-7, 3) = -1 mod(7, -3) = 1 modulo(-7, 3) = 2 modulo(7, -3) = -2
Exponentiation
The operator ** takes an integer or a real exponent. An integer
base with a non-negative integer exponent gives an integer, so the arithmetic
is exact until it overflows the kind. A negative integer exponent is legal but
useless: the result is 0 for any base except 1 and -1, because an integer
cannot hold a fraction. A real exponent always gives a real result, which makes
x ** 0.5 a square root.
program powers
implicit none
integer :: base, e
real :: x
base = 2
e = -1
x = 2.0
print *, base ** e
print *, x ** e
print *, x ** 0.5, sqrt(x)
print *, 2.0 ** 3, 2 ** 3.0
end program powers
The integer expression base ** e is 0, since 2 to the power -1 is
one half. The real expression gives 0.5, and the real square root agrees with
the sqrt function. The last line shows that the same mathematical
operation can be written with the base or the exponent as a real; the result of
a mixed expression is real.
$ gfortran powers.f90 -o powers
$ ./powers
0
0.500000000
1.41421354 1.41421354
8.00000000 8.00000000
Precedence and associativity
An expression with several operators is grouped by precedence, and operators
of equal precedence are applied from left to right, except **,
which is applied from right to left. The table lists the groups from the
highest precedence to the lowest. Parentheses override everything and cost
nothing.
| Precedence | Operators | Associativity |
|---|---|---|
| 1 | ** | right |
| 2 | unary +, - | right |
| 3 | *, / | left |
| 4 | binary +, - | left |
| 5 | // | left |
| 6 | relational operators | not chainable |
| 7 | .not. | unary |
| 8 | .and. | left |
| 9 | .or. | left |
| 10 | .eqv., .neqv. | left |
The two entries that surprise newcomers are the top ones. Exponentiation binds
tighter than the unary minus, so -a ** 2 is
-(a ** 2) and not (-a) ** 2. Exponentiation is also
right associative, so 2 ** 3 ** 2 is 2 ** (3 ** 2),
which is 512 and not 64. Subtraction and division stay left associative, so
a - b - c is (a - b) - c.
program precedence
implicit none
integer :: a, b, c
a = 2
b = 3
c = 4
print *, a + b * c
print *, (a + b) * c
print *, a ** b + c
print *, -a ** 2
print *, a - b - c
end program precedence
The first line is 14 because the multiplication is done before the addition, and the second is 20 because the parentheses change the grouping. The exponentiation is computed before the addition and before the unary minus, so the third line is 12 and the fourth is -4. The last line is -5, which shows the left-to-right grouping of the two subtractions.
$ gfortran prec.f90 -o prec
$ ./prec
14
20
12
-4
-5
Relational operators
A relational operator compares two values and produces a logical value. Every
operator has a symbolic form and a dotted form that predates it:
== is .eq., /= is .ne.,
< is .lt., <= is
.le., > is .gt., and
>= is .ge.. The two forms are interchangeable,
and old programs use the dotted forms almost exclusively.
program relops
implicit none
integer :: a, b
a = 5
b = 3
print *, a == b, a /= b, a < b, a <= b, a > b, a >= b
print *, a .eq. b, a .ne. b, a .lt. b, a .le. b, a .gt. b, a .ge. b
print *, a .LT. b, .FALSE. .EQV. .FALSE.
end program relops
The first two lines print the same six results, which are
F T F F T T. The last line shows that the dotted forms are case
insensitive like the rest of the language, so .LT. means the same
as .lt.. The comparison of two equal logical values is true, so
the last result is T.
$ gfortran relops.f90 -o relops $ ./relops F T F F T T F T F F T T F T
Comparing character strings
Relational operators also compare character strings. The comparison is
lexicographic on the character codes, so it is case sensitive: an uppercase
letter comes before the corresponding lowercase letter. Before comparing,
Fortran pads the shorter operand with blanks, so two strings of different
lengths can be equal. The functions len still report the declared
lengths, which is why the padding is easy to overlook.
program strcmp
implicit none
print *, 'abc' < 'abd', 'abc' > 'abd'
print *, 'abc' == 'abc '
print *, len('abc'), len('abc ')
print *, 'Fortran' < 'fortran'
print *, '10' < '9'
end program strcmp
The strings abc and abd differ in the last
character, so the first is smaller. The second line compares a string of
length 3 with one of length 5 and gets true, because the shorter one is padded
with two blanks first. The comparison of Fortran with
fortran is true because F has a smaller code than
f. The last comparison is true as well: the strings are compared
character by character, and 1 is smaller than 9, so
this is not a numeric comparison at all.
$ gfortran strcmp.f90 -o strcmp
$ ./strcmp
T F
T
3 5
T
T
Logical operators
Logical values combine with five operators: .and.,
.or., .not., .eqv. and
.neqv.. The last two test whether two logical values are the
same or different, and they have the lowest precedence of all. The dot is part
of every name; and without dots is just an identifier.
program logic
implicit none
logical :: p, q
p = .true.
q = .false.
print *, p .and. q, p .or. q, .not. p
print *, p .eqv. q, p .neqv. q
print *, p .and. .not. q
print *, (p .or. q) .and. q
end program logic
With p true and q false, the conjunction is false,
the disjunction is true, and the negation of p is false. The
equivalence of the two different values is false and their non-equivalence is
true. The third line combines a negation with a conjunction, and the last one
shows the usual trap of the form: the parenthesised disjunction is true, but
the conjunction with q makes the whole expression false.
$ gfortran logic.f90 -o logic $ ./logic F T F F T T F
Negation is not a bit operation
Because .not. sits below the relational operators in the
precedence table, .not. a > b means
.not. (a > b). The operator also accepts only logical
operands, so it cannot be used for the bitwise complement of an integer; the
intrinsic function not does that job. Keeping the parentheses in
the source makes the intention visible to a reader.
program notprec
implicit none
integer :: a, b
logical :: r
a = 5
b = 3
r = .not. a > b
print *, r
r = .not. (a > b)
print *, r
end program notprec
Both assignments produce the same value, because the relational operator binds
tighter. Since a > b is true, the negation is false. Written
without the parentheses the statement is correct, but a reader has to recall
the precedence table to see it, so the second form is the better style.
$ gfortran notprec.f90 -o notprec $ ./notprec F F
String concatenation
The operator // joins two character strings into a new one. The
result has the sum of the lengths of the operands, and blanks inside an operand
are kept. This is the only operator that works on characters, and it has a
lower precedence than addition, so it never competes with arithmetic.
program concat
implicit none
character(len=10) :: name
character(len=3) :: prefix
name = 'Fortran'
prefix = 'Hi '
print *, prefix // name
print *, len(prefix // name), len_trim(prefix // name)
print *, 'Fortran ' // '2018'
end program concat
The variables are longer than their values, so the unused positions are blanks.
The concatenation has length 13, which is the sum of 3 and 10, and only
len_trim reports the 10 characters that carry text. The last line
joins two literals and produces a string of length 12. Concatenation never
adds a separator, so a blank has to be part of one of the operands.
$ gfortran concat.f90 -o concat
$ ./concat
Hi Fortran
13 10
Fortran 2018
Mixing integers and reals
When an arithmetic operator has one integer and one real operand, the integer is converted to real and the operation is done in real arithmetic. Conversion happens at the operator, not before the expression, so an all-integer subexpression is still evaluated as integers. Assigning a real result to an integer variable truncates it, and assigning an integer to a real is exact.
program mixed
use, intrinsic :: iso_fortran_env, only: real64
implicit none
integer :: a, b
real(real64) :: x
a = 7
b = 2
x = a / b
print *, 'integer division first: ', x
x = real(a, real64) / real(b, real64)
print *, 'conversion first: ', x
x = real(a) / b
print *, 'one real operand: ', x
print *, a / b * 2.0_real64
end program mixed
The first assignment divides 7 by 2 as integers, gets 3, and only then converts
the result to double precision. The second converts both operands first and
gets 3.5. The third does the same with a single conversion, because one real
operand is enough to make the division real. The last line multiplies the
integer result of the division by a real, so it prints 6.0 and not 7.0. The
real function with a kind argument is the reliable way to convert,
as described in the data types article.
$ gfortran mixed.f90 -o mixed $ ./mixed integer division first: 3.0000000000000000 conversion first: 3.5000000000000000 one real operand: 3.5000000000000000 6.0000000000000000
A complete example
The program below uses the operators together. It computes the value of an
investment after a number of years with compound interest, which needs a power,
a sum, a product, and a comparison. The formula is
principal * (1 + rate) ** years, and everything is in default
real precision.
program compound
implicit none
real :: principal, rate, amount
integer :: years
principal = 1000.0
rate = 0.05
years = 10
amount = principal * (1.0 + rate) ** years
print *, 'amount after', years, 'years:', amount
print *, 'interest:', amount - principal
print *, 'more than doubled:', amount > 2.0 * principal
end program compound
The power is computed first, then multiplied by the principal. The parentheses
around the sum are essential: without them the exponent would apply to
rate alone. The interest is the difference between the final and
the initial amount. The comparison against twice the principal is false,
because 1000 grows to about 1628 in ten years at five percent, which is less
than 2000.
$ gfortran compound.f90 -o compound $ ./compound amount after 10 years: 1628.89355 interest: 628.893555 more than doubled: F
Next steps
The intrinsic numeric functions
article covers abs, mod, the rounding functions and
the trigonometric functions, and
Fortran conditionals shows how the logical
values produced by the relational operators drive the control flow of a
program.
Source
Fortran 2018 standard (J3/18-007r1), section 10.3.2 on operator precedence
In this article we have used the arithmetic operators, seen how integer
division truncates toward zero, compared the two remainder functions, ordered
the operators by precedence, compared numbers and strings, combined logical
values, joined strings with //, and mixed integers with reals.
The previous article, Fortran literals and
constants, describes how the values in these expressions are written.
Author
List all Fortran tutorials.