Fortran formatted output
last modified November 14, 2026
Fortran has two ways to print a value. List-directed output, written
print * or write (*, *), lets the compiler choose
the layout: it decides how wide each field is and how many digits to show.
Formatted output gives that decision to the programmer through a
format, a string of edit descriptors that says how many characters
each value occupies, how many decimals to print and where to put blanks and
line breaks. This article starts from the list-directed form, then explains
the descriptors for integers, fixed-point reals, scientific notation and
text, and finishes with format statements and aligned tables.
List-directed output
The asterisk in print *, n, x, 'done' is a placeholder for a
format that the compiler writes for itself. The values are separated by
blanks and each number gets a field wide enough for any value of its type, so
columns do not line up with anything the programmer planned. A character
constant is printed as it is, with no padding, which is why it follows the
number directly after the number's trailing blanks.
program o1
implicit none
integer :: n
real :: x
n = 42
x = 3.14159
print *, 'list-directed:'
print *, n, x, 'done'
print *, 'formatted:'
write (*, '(i4, f8.3, 1x, a)') n, x, 'done'
end program o1
The integer occupies twelve characters and the single-precision real
eighteen, most of the latter being blanks, and done starts right
after the real's padding.
The formatted line is shorter and controlled: i4 reserves four
characters for the integer, f8.3 eight characters for the real
with three decimals, 1x one blank, and a the
remaining characters of done. The following sections explain
each of those descriptors; reading them in order is the quickest way to
understand the format string.
$ gfortran o1.f90 -o o1
$ ./o1
list-directed:
42 3.14159012 done
formatted:
42 3.142 done
Integers and the i descriptor
The form of the integer descriptor is iw, where w
is the width of the field, the number of character positions reserved
for the value. The value is right-aligned in that
field, so wider fields push the digits to the right and make a column of
numbers line up on their last digit. The form iw.m also demands
at least m digits, filling with leading zeros when the number is
shorter. The special width i0 uses exactly the characters the
number needs and is the right choice for building strings, as in the
internal files article.
program o2
implicit none
write (*, '(i6)') 7
write (*, '(i6)') 42
write (*, '(i6)') -3
write (*, '(i6)') 1234
write (*, '(i0)') 1234
write (*, '(i4.2)') 7
write (*, '(i2)') 1234
end program o2
The first four lines show the same width holding numbers of different
lengths, all ending in the same column. The fifth line prints
1234 with no padding because i0 asks for the
minimum. The sixth uses i4.2, which requires two digits, so the
seven appears as 07. The last line gives a width of two to a
four-digit number; the value does not fit, and Fortran fills the whole field
with asterisks rather than printing a misleading prefix.
$ gfortran o2.f90 -o o2
$ ./o2
7
42
-3
1234
1234
07
**
Reals and the f descriptor
The descriptor for a number in ordinary decimal notation is fw.d:
w characters in total, of which d come after the
decimal point. The decimal point itself and the minus sign, when present, are
part of the width, so a field must have room for all of them. The value is
rounded to d decimals, and a number that does not fit produces
asterisks like the integer did.
program o3
implicit none
write (*, '(f8.2)') 3.14159
write (*, '(f8.2)') -2.5
write (*, '(f6.3)') 1.0 / 3.0
write (*, '(f10.4)') 12345.6789
write (*, '(f3.2)') 3.14159
write (*, '(f8.2)') 0.005
write (*, '(f8.2)') 0.015
end program o3
The first two lines round 3.14159 to two decimals and keep the minus sign
inside the eight characters. The third shows three decimals of one third.
The fourth is a reminder that the number of digits printed cannot exceed the
precision stored: a default real holds about seven significant
decimal digits, so the last two digits of 12345.6789 are lost
before formatting even starts. The fifth line is too narrow and prints
asterisks. The last two show the effect of binary representation: neither
0.005 nor 0.015 is exact in binary, and both are stored slightly below their
decimal values, so they round down to 0.00 and 0.01.
$ gfortran o3.f90 -o o3
$ ./o3
3.14
-2.50
0.333
12345.6787
***
0.00
0.01
Scientific notation: e, es and g
Very large and very small numbers need an exponent. The e
descriptor, written ew.d, prints the number as a value between
0 and 1, called the mantissa, followed by E and a signed exponent,
so 6.022 times ten to the twenty-third appears as 0.602E+24. The es descriptor puts exactly
one non-zero digit before the decimal point and is the form most people
expect from a calculator. The g descriptor chooses between
fixed-point and scientific notation for each value, depending on its
magnitude, and g0 prints the shortest useful form.
program o4
implicit none
real :: avogadro, charge
avogadro = 6.02214076e23
charge = 1.602176634e-19
write (*, '(e12.3)') avogadro
write (*, '(es12.3)') avogadro
write (*, '(es12.3)') charge
write (*, '(g12.4)') avogadro
write (*, '(g12.4)') charge
write (*, '(g0)') 255.5
end program o4
The first line shows the scaled mantissa of the e descriptor,
the second the single leading digit of es, and the third the same
form for a tiny number with a negative exponent. The two g lines
pick scientific notation because both values are far from one, and
g0 prints the ordinary decimal form for 255.5. All of them are
limited by the precision of a default real: write
6.02214076_real64 and declare the variable as
real(real64) to keep more digits.
$ gfortran o4.f90 -o o4 $ ./o4 0.602E+24 6.022E+23 1.602E-19 0.6022E+24 0.1602E-18 255.500000
Text, blanks and records
The a descriptor prints a character value; with a width, as in
a8, a shorter value is right-aligned in the field, which is handy
for a column of headings. x inserts blanks, / ends
the current record (one line of output) and starts a new one, and a
number in front of a descriptor or a parenthesised group repeats it. A
character constant written inside the format string is printed literally,
which is how labels such as ' = ' get between two values.
program o5
implicit none
integer :: i
write (*, '(a)') 'Report'
write (*, '(a, /, a)') 'Line one', 'Line two'
write (*, '(a, 3x, a)') 'left', 'right'
write (*, '(a8)') 'right'
write (*, '(a, " = ", f6.1)') 'half', 0.5
write (*, '(3(i3, 1x))') 1, 2, 3
do i = 1, 3
write (*, '(a, i2, a, f6.1)') 'item ', i, ' = ', i * 1.5
end do
end program o5
The second statement prints two records because the slash between the two
a descriptors ends the first one. The third puts three blanks
between the words, while the fourth shows that a8 aligns a short
word to the right of its field. The fifth mixes a literal from the format
with a value, the sixth repeats the group (i3, 1x) three times,
and the loop prints three lines whose numbers end in the same column.
$ gfortran o5.f90 -o o5 $ ./o5 Report Line one Line two left right right half = 0.5 1 2 3 item 1 = 1.5 item 2 = 3.0 item 3 = 4.5
A formatted table
A table is a header, a rule and a row per data item, all using the same widths. Choosing the widths is the whole design: the widest value that can appear in a column decides its width, and the same format is then reused for the header and for every row. The program below prints the squares and square roots of the numbers from one to five, with an integer column for the square and a real column for the root.
program o6
implicit none
integer :: i
write (*, '(a6, a10, a12)') 'n', 'square', 'sqrt'
write (*, '(a)') repeat('-', 28)
do i = 1, 5
write (*, '(i6, i10, f12.4)') i, i * i, sqrt(real(i))
end do
end program o6
The widths six, ten and twelve add up to the 28 characters of the rule. The
header uses the same widths with a, so each word sits above its
column, right-aligned like the numbers below it. sqrt needs a
real argument, hence real(i), and f12.4 prints four
decimals with the decimal points lined up, because every field is the same
width and every value has the same number of decimals.
$ gfortran o6.f90 -o o6
$ ./o6
n square sqrt
----------------------------
1 1 1.0000
2 4 1.4142
3 9 1.7321
4 16 2.0000
5 25 2.2361
Format statements and repetition
A format need not sit inside the write. A labelled
format statement at the end of the program holds it, and the
write refers to the label instead of spelling the string out.
When the values outnumber the descriptors, Fortran does not stop: it
reverts to the beginning of the format and starts a new record, which
is why a four-value format applied to eight values produces two lines. The
form *(...), introduced in Fortran 2008, repeats the group as
often as needed without starting a new record.
program o7
implicit none
integer :: a(8)
a = [1, 2, 3, 4, 5, 6, 7, 8]
write (*, 100) a
write (*, 200) a
100 format (4(i3))
200 format (*(i3))
end program o7
The first write uses the labelled format 4(i3), which holds four
values in one record; the fifth value starts a new record and the format is
reused from the beginning. The second write uses the unlimited repeat, so all
eight values stay in a single line of 24 characters. The array is printed in
element order, which for a one-dimensional array is simply the order of the
elements.
$ gfortran o7.f90 -o o7 $ ./o7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
Next steps
The internal files article uses the same
descriptors to write into a character variable instead of the screen. The
reading input article pairs the formats
with read, and the strings
article explains the character values that a prints, and the
files article applies formatted output to a file
opened with open.
Source
Fortran 2018 standard (J3/18-007r1)
Fortran-lang: learning resources
In this article we have replaced the compiler's layout with our own: integer fields, fixed-point and scientific reals, text and blanks, repeated groups, format statements and tables. The previous article, Fortran internal files, puts the same descriptors to work inside a string.
Author
List all Fortran tutorials.