ZetCode

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.

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

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

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

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

PrecedenceOperatorsAssociativity
1**right
2unary +, -right
3*, /left
4binary +, -left
5//left
6relational operatorsnot 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.

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

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

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

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

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

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

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

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

GNU Fortran: operators

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

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.