ZetCode

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.

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

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

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

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

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

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

o7.f90
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)

GNU Fortran manual

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

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.