cv.cm

Coding · Programming languages

Fortran tutorial for beginners

7 min read

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 hello
gfortran 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.

TypeExample declarationNotes
integerinteger :: count = 3Usually 32-bit; integer(int64) for 64-bit
realreal :: xUsually single precision
real(real64)real(real64) :: yDouble precision, the usual choice for science
complexcomplex :: z = (1.0, 2.0)Built-in complex numbers
logicallogical :: done = .false..true. / .false., operators .and., .or., .not.
charactercharacter(len=20) :: nameFixed-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 types

The 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 control

do 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 demo

Arguments 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 arrays

Multi-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 parse

Reading 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.817

The 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.

All coding tutorials