Operators in Fortran
Master arithmetic, relational, logical, and string operators in Fortran, including precedence rules and the language-specific power operator
Operators are the verbs of any programming language - they transform values into new values. Fortran, designed from the start to translate mathematical formulas into machine code, has a particularly rich and well-considered set of operators that closely mirror standard mathematical notation.
As a statically and strongly typed imperative language, Fortran enforces strict rules about which operators apply to which types. The compiler will catch attempts to add a string to an integer, but it will silently perform type promotion when mixing integers and reals in arithmetic - a behavior that has tripped up Fortran programmers since 1957.
This tutorial covers the four main operator categories in Fortran: arithmetic, relational (comparison), logical, and the string concatenation operator. We’ll also examine operator precedence and Fortran’s unique dual syntax for relational operators - a fascinating relic of its punch-card origins.
Arithmetic Operators
Fortran provides the standard arithmetic operators plus an exponentiation operator (**) that predates most other languages.
| Operator | Meaning | Example |
|---|---|---|
+ | Addition | a + b |
- | Subtraction (or unary negation) | a - b, -a |
* | Multiplication | a * b |
/ | Division | a / b |
** | Exponentiation (power) | a ** b |
Create a file named arithmetic.f90:
| |
Integer vs Real Division - A Classic Pitfall
When both operands of / are integers, Fortran performs integer division and truncates the result. 17 / 5 evaluates to 3, not 3.4. To get a real result, at least one operand must be real: 17.0 / 5 or real(17) / 5 both produce 3.4. The mod intrinsic returns the remainder.
Relational Operators
Fortran has two equivalent sets of relational operators. The modern symbolic form was added in Fortran 90; the older .lt. style dates to the original 1957 FORTRAN, when punch card hardware did not support < or > characters.
| Modern | Classic | Meaning |
|---|---|---|
== | .eq. | Equal to |
/= | .ne. | Not equal to |
< | .lt. | Less than |
<= | .le. | Less than or equal to |
> | .gt. | Greater than |
>= | .ge. | Greater than or equal to |
Create a file named relational.f90:
| |
Floating-Point Equality
The last line will print F (false) because 0.1 + 0.2 does not equal 0.3 exactly in binary floating point. For real number comparison, always test that the absolute difference is below a small tolerance: abs(x - y) < 1.0e-6.
Logical Operators
Logical operators in Fortran always use the dotted form - there is no symbolic equivalent like && or ||. They operate on values of type logical.
| Operator | Meaning |
|---|---|
.not. | Logical negation |
.and. | Logical AND |
.or. | Logical OR |
.eqv. | Logical equivalence (XNOR) |
.neqv. | Logical non-equivalence (XOR) |
Create a file named logical_ops.f90:
| |
No Short-Circuit Evaluation
Unlike C or Python, Fortran does not guarantee that the second operand of .and. or .or. will be skipped when the result is already determined. The compiler may evaluate both sides. Never rely on the left side of .and. to guard a potentially unsafe right side - use a nested if instead.
String Concatenation
Fortran uses // (double slash) for string concatenation. This is one of the few language-specific operators that often surprises programmers from other backgrounds.
Create a file named string_ops.f90:
| |
Operator Precedence
Fortran’s precedence rules follow standard mathematical conventions, with one notable feature: exponentiation is right-associative, so 2 ** 3 ** 2 evaluates as 2 ** (3 ** 2) = 2 ** 9 = 512.
From highest to lowest precedence:
**(exponentiation, right-associative)*,/- Unary
+,- - Binary
+,- //(string concatenation)- Relational operators (
==,/=,<, etc.) .not..and..or..eqv.,.neqv.
Create a file named precedence.f90:
| |
Running with Docker
| |
Expected Output
Output from arithmetic.f90:
Integer 17 / 5 = 3
Integer 17 mod 5 = 2
Real 17.0 / 5.0 = 3.40000010
2.0 ** 10 = 1024.00000
1 + 2.5 = 3.50000000
2.0 ** (-3) = 0.125000000
Output from relational.f90:
10 == 20 : F
10 /= 20 : T
10 < 20 : T
10 >= 20 : F
10 .lt. 20 : T
10 .eq. 20 : F
(10 * 2) == 20 : T
0.1 + 0.2 == 0.3 : F
Output from logical_ops.f90:
.not. true : F
true .and. false: F
true .or. false: T
true .eqv. true : T
true .neqv. false: T
Eligible: T
Output from string_ops.f90:
Full name: [Grace Hopper]
Untrimmed: [Grace Hopper ]
'abc' < 'abd' : T
Output from precedence.f90:
2 ** 3 ** 2 = 512
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
1 < 2 .and. 3 > 2 : T
-2 ** 2 = -4
Key Concepts
- Integer division truncates -
17 / 5is3; promote at least one operand torealfor true division - Two relational syntaxes coexist -
==and.eq.mean the same thing; the dotted form is a holdover from punch-card hardware - Logical operators are always dotted - Fortran uses
.and.,.or.,.not.- never&&or|| - No short-circuit evaluation - The compiler may evaluate both operands of
.and.and.or.; never use them as guards **is exponentiation and right-associative -2 ** 3 ** 2is512, and-2 ** 2is-4(the**binds tighter than unary minus)//concatenates strings - Fixed-length character variables are space-padded; usetrim()to remove trailing spaces- Mixed-mode arithmetic promotes - An integer combined with a real is converted to real automatically; the assigned variable’s type may still cause truncation
- Never test reals with
==- Compare the absolute difference against a tolerance instead
Comments
Loading comments...
Leave a Comment