Coding · Programming languages
Fortran tutorial for beginners
Short answer
Fortran is a compiled, statically typed language built for numerical and scientific computing. Modern Fortran (Fortran 90 and later standards) has free-form source, modules, dynamic arrays and powerful whole-array operations, and compilers turn it into very fast machine code. Install the free gfortran compiler, save code in a .f90 file and build it with gfortran hello.f90 -o hello.
What Fortran is and who uses it
Fortran ("formula translation") was developed at IBM by a team led by John Backus in the 1950s and is one of the oldest programming languages still in active use. It is standardized by ISO; major revisions include Fortran 90, 95, 2003, 2008, 2018 and 2023. The old fixed-form style (upper-case FORTRAN 77, code starting in column 7) is still compiled, but new code uses the free-form syntax shown here.
Fortran is used where heavy number crunching matters: weather and climate models, computational fluid dynamics, physics and chemistry simulations, and many programs that run on supercomputers. The reference versions of the BLAS and LAPACK linear algebra libraries, used underneath tools such as NumPy and MATLAB, are written in Fortran.
Install a compiler and run Hello, world
gfortran, part of GCC, is free and available on Linux (package gfortran), macOS (Homebrew gcc) and Windows (MSYS2 or WSL). Intel's ifx and LLVM Flang are other compilers. The Fortran Package Manager (fpm) can create and build projects.
program hello
implicit none
print *, "Hello, world!"
end program hellogfortran hello.f90 -o hello
./hello
# Hello, world!print * uses list-directed output, which chooses spacing for you (note the leading space). Fortran is not case-sensitive: PRINT, Print and print are the same.
Variables and basic types
All declarations come at the top of a program unit, before executable statements. Always write implicit none: without it, undeclared names starting with I to N are silently integers and all others are reals.
| Type | Example declaration | Notes |
|---|---|---|
| integer | integer :: count = 3 | Usually 32-bit; integer(int64) for 64-bit |
| real | real :: x | Usually single precision |
| real(real64) | real(real64) :: y | Double precision, the usual choice for science |
| complex | complex :: z = (1.0, 2.0) | Built-in complex numbers |
| logical | logical :: done = .false. | .true. / .false., operators .and., .or., .not. |
| character | character(len=20) :: name | Fixed-length string, padded with spaces |
program types
use, intrinsic :: iso_fortran_env, only: int64, real64
implicit none
integer :: count = 3
integer(int64) :: big = 9000000000_int64
real(real64) :: third
logical :: done = .false.
character(len=:), allocatable :: name
third = 1.0_real64 / 3.0_real64
name = "Ana"
print *, count, big, third, done, name
end program typesThe suffix _real64 sets the kind (precision) of a literal. Without it, 1.0 is a single-precision constant, which loses digits when assigned to a double-precision variable.
Control flow
program control
implicit none
integer :: i, total, score
total = 0
do i = 1, 10
if (mod(i, 2) == 0) cycle ! skip even numbers
total = total + i
end do
print *, "sum of odd numbers:", total ! 25
score = 85
if (score >= 90) then
print *, "A"
else if (score >= 80) then
print *, "B"
else
print *, "C"
end if
select case (score)
case (90:)
print *, "excellent"
case (80:89)
print *, "good"
case default
print *, "keep going"
end select
end program controldo i = 1, 10 includes both ends, and an optional third value sets the step (do i = 10, 1, -1). cycle skips to the next iteration and exit leaves the loop. do while (condition) and a plain do with exit are also available. Comments start with !.
Functions, subroutines and modules
Fortran has two kinds of procedures: a function returns a value and is used in expressions; a subroutine is called with call and returns results through its arguments. Put procedures in a module so the compiler can check every call.
module geometry
implicit none
contains
function circle_area(r) result(a)
real, intent(in) :: r
real :: a
a = 3.14159 * r**2
end function circle_area
subroutine swap(a, b)
integer, intent(inout) :: a, b
integer :: tmp
tmp = a
a = b
b = tmp
end subroutine swap
end module geometry
program demo
use geometry
implicit none
integer :: x, y
x = 1
y = 2
print *, circle_area(2.0) ! about 12.566
call swap(x, y)
print *, x, y ! 2 1
end program demoArguments are passed by reference, so a procedure can change the caller's variables. intent(in), intent(out) and intent(inout) document and enforce what each argument may do. ** is the power operator.
Arrays: Fortran's signature feature
Arrays are central to Fortran. Indexes start at 1 by default (any lower bound is allowed), arithmetic works on whole arrays without loops, slices use a(start:end), and many intrinsic functions operate on arrays directly.
program arrays
implicit none
integer :: i
real :: a(5), b(5)
real, allocatable :: c(:)
integer :: m(2, 3)
a = [(real(i), i = 1, 5)] ! 1.0 2.0 3.0 4.0 5.0
b = 2.0 * a + 1.0 ! whole-array arithmetic
print *, b(2:4) ! 5.0 7.0 9.0
print *, sum(a), maxval(b) ! 15.0 11.0
allocate(c(10))
c = 0.0
print *, size(c) ! 10
deallocate(c)
m = reshape([1, 2, 3, 4, 5, 6], [2, 3])
print *, m(2, 1) ! 2 (column-major order)
end program arraysMulti-dimensional arrays are stored in column-major order: the first index changes fastest in memory, the opposite of C. For speed, make the innermost loop run over the first index. Other useful intrinsics are matmul, dot_product, transpose, minval and count. Modern Fortran also offers do concurrent loops and coarrays for parallel programs.
Error handling
Fortran has no exceptions. Statements that can fail accept a status argument: iostat for input and output, stat for allocate. Check the value and react; if you omit it, an error stops the program. error stop ends the program with an error.
program parse
implicit none
character(len=20) :: text
integer :: n, ios
text = "abc"
read(text, *, iostat=ios) n
if (ios /= 0) then
print *, "not a number: ", trim(text)
else
print *, "n =", n
end if
end program parseReading from a character variable, as above, is called an internal read and is the usual way to convert a string to a number.
A small complete program: mean and standard deviation
module stats
implicit none
integer, parameter :: dp = kind(1.0d0)
contains
pure function mean(x) result(m)
real(dp), intent(in) :: x(:)
real(dp) :: m
m = sum(x) / size(x)
end function mean
pure function std_dev(x) result(s)
real(dp), intent(in) :: x(:)
real(dp) :: s
s = sqrt(sum((x - mean(x))**2) / (size(x) - 1))
end function std_dev
end module stats
program main
use stats
implicit none
real(dp) :: values(5)
values = [2.0_dp, 4.0_dp, 4.0_dp, 5.0_dp, 7.0_dp]
print '(a, f6.3)', "mean = ", mean(values)
print '(a, f6.3)', "std dev = ", std_dev(values)
end program main
! mean = 4.400
! std dev = 1.817The x(:) declaration is an assumed-shape array, so the functions accept arrays of any length. pure promises that a function has no side effects. The format '(a, f6.3)' prints a string followed by a real number 6 characters wide with 3 decimals.
Where to go next
- fortran-lang.org: the Learn section with a quickstart tutorial and best practices.
- The GNU Fortran (gfortran) manual for compiler options and intrinsic procedures.
- Try the Fortran Package Manager (fpm) to create projects and use libraries such as the Fortran standard library (stdlib).
- Compile with warnings and runtime checks while learning, for example
gfortran -Wall -fcheck=all.
FAQ
Is Fortran still used today?
Yes. Fortran remains widely used in scientific computing and high-performance computing, especially for climate, weather, physics and engineering simulations, and the language standard is still being updated.
What is the difference between .f and .f90 files?
By convention, .f and .for files use the old fixed-form layout of FORTRAN 77, where columns matter, while .f90 files use free-form source. The .f90 extension is used for free-form code of any modern standard, not only Fortran 90.
Why is Fortran fast?
The language was designed for numerical work: arrays are built in, aliasing rules let compilers optimize aggressively, and decades of compiler work target it. Well-written C or C++ can reach similar speed.
Do Fortran arrays start at 0 or 1?
They start at 1 by default, but you can choose any lower bound, for example real :: a(0:9) declares ten elements indexed from 0 to 9.