Fortran data types and kinds
last modified November 14, 2026
Fortran has five intrinsic data types: integer,
real, complex, logical, and
character. Each type comes in one or more kinds, which
select the size and precision of the values. This article describes the types,
shows how to choose a kind in a portable way, and looks at the limits of
integers and floating-point numbers.
Intrinsic types
The table lists the five types. Derived types, which programmers define themselves, are described in a later article.
| Type | Holds | Example declaration |
|---|---|---|
integer | whole numbers | integer :: count |
real | floating-point numbers | real :: height |
complex | pairs of real numbers | complex :: z |
logical | .true. or .false. | logical :: done |
character | text of a given length | character(len=20) :: name |
A kind is written in parentheses after the type name, for example
integer(kind=8) or just integer(8). A declaration
without a kind uses the default kind of the type. The function
kind returns the kind of a variable, so we can ask the compiler what
the defaults are.
Default kinds
Kinds are small integers, and the standard does not say what they mean; every
compiler chooses its own numbers. The program prints the default kind of every
type. It also declares a variable of type double precision, the
old way of asking for a real number with more than the default precision.
program kinds
implicit none
integer :: i
real :: r
double precision :: d
complex :: z
logical :: flag
character(len=5) :: s
print *, 'integer: ', kind(i)
print *, 'real: ', kind(r)
print *, 'double precision: ', kind(d)
print *, 'complex: ', kind(z)
print *, 'logical: ', kind(flag)
print *, 'character: ', kind(s)
end program kinds
In gfortran the kind number of an integer, real or logical equals the number of
bytes the value takes, so the default integer and real have 4 bytes (32 bits)
and double precision has 8. A default complex number is a pair of
default reals, and a character has kind 1. Other compilers number kinds
differently, so a program should never depend on the numbers themselves.
$ gfortran kinds.f90 -o kinds $ ./kinds integer: 4 real: 4 double precision: 8 complex: 4 logical: 4 character: 1
Kind constants of iso_fortran_env
The intrinsic module iso_fortran_env provides named constants for
the sizes in bits: int8, int16, int32,
int64 for integers and real32, real64,
real128 for reals. They are the portable way to say "a 64-bit
integer" or "a double-precision real".
program envkinds
use, intrinsic :: iso_fortran_env, only: int8, int16, int32, int64, &
real32, real64, real128
implicit none
print *, 'int8: ', int8
print *, 'int16: ', int16
print *, 'int32: ', int32
print *, 'int64: ', int64
print *, 'real32: ', real32
print *, 'real64: ', real64
print *, 'real128:', real128
end program envkinds
The program imports the constants with use, intrinsic and prints
them. In gfortran they are the byte sizes, so real64 is 8, and the
128-bit real is available as kind 16. The names are what the program should use:
real(real64) reads as a declaration of a 64-bit real on every
compiler, whatever number it uses internally.
$ gfortran envkinds.f90 -o envkinds $ ./envkinds int8: 1 int16: 2 int32: 4 int64: 8 real32: 4 real64: 8 real128: 16
Integers
An integer is a signed whole number. The function huge returns the
largest value of the kind of its argument. The literal 1_int8
used below is an integer of kind int8; the suffix syntax is
described in the literals article.
program limits
use, intrinsic :: iso_fortran_env, only: int8, int16, int32, int64
implicit none
print *, 'int8: ', huge(1_int8)
print *, 'int16: ', huge(1_int16)
print *, 'int32: ', huge(1_int32)
print *, 'int64: ', huge(1_int64)
end program limits
An 8-bit integer reaches 127, a 16-bit integer 32767, a 32-bit integer 2147483647, and a 64-bit integer 9223372036854775807. Fortran has no unsigned integer types in the standard, so these are all signed ranges.
$ gfortran limits.f90 -o limits $ ./limits int8: 127 int16: 32767 int32: 2147483647 int64: 9223372036854775807
Integer overflow
When a result does not fit the kind, the standard says nothing about what happens, and the compiler is free to do anything. In practice the value wraps around, and the program continues with a wrong number.
program overflow
implicit none
integer :: i
i = huge(i)
print *, 'largest: ', i
i = i + 1
print *, 'plus one:', i
end program overflow
The program stores the largest value in i and adds one. The result
is the most negative value. The run-time checks enabled by
-fcheck=all do not catch integer overflow. Compiling with
-ftrapv makes the same program abort with a signal at the
addition instead, which is useful while testing. When a computation can exceed
32 bits, choose a wider kind such as int64.
$ gfortran overflow.f90 -o overflow $ ./overflow largest: 2147483647 plus one: -2147483648
Reals
A real holds a floating-point number. The functions
huge, tiny, epsilon,
precision and range describe a real kind:
huge is the largest finite value, tiny the smallest
positive normal value, epsilon the smallest number that changes
1.0 when added to it, precision the number of reliable decimal
digits, and range the decimal exponent range.
program reallimits
use, intrinsic :: iso_fortran_env, only: real32, real64
implicit none
real(real32) :: s
real(real64) :: d
print *, 'real32 huge: ', huge(s)
print *, 'real32 tiny: ', tiny(s)
print *, 'real32 epsilon: ', epsilon(s)
print *, 'real32 precision:', precision(s)
print *, 'real32 range: ', range(s)
print *, 'real64 huge: ', huge(d)
print *, 'real64 tiny: ', tiny(d)
print *, 'real64 epsilon: ', epsilon(d)
print *, 'real64 precision:', precision(d)
print *, 'real64 range: ', range(d)
end program reallimits
A 32-bit real has about 6 reliable decimal digits and values up to about
3.4e38. A 64-bit real has about 15 digits and reaches 1.8e308. The
epsilon values, about 1.2e-7 and 2.2e-16, are the relative size
of the gap between neighbouring numbers: they show why single precision is
rarely enough for scientific work. gfortran writes the exponent of a 64-bit real
with three digits, such as E-016, in list-directed output.
$ gfortran reallimits.f90 -o reallimits $ ./reallimits real32 huge: 3.40282347E+38 real32 tiny: 1.17549435E-38 real32 epsilon: 1.19209290E-07 real32 precision: 6 real32 range: 37 real64 huge: 1.7976931348623157E+308 real64 tiny: 2.2250738585072014E-308 real64 epsilon: 2.2204460492503131E-016 real64 precision: 15 real64 range: 307
Representation errors
Most decimal fractions have no exact binary representation. The number 0.1 is
stored as the closest binary fraction, and the error is larger in single
precision. The program writes the stored values with 18 significant digits in
scientific notation (the edit descriptor es26.17e3) and compares
a sum.
program precision_demo
use, intrinsic :: iso_fortran_env, only: real32, real64
implicit none
real(real32) :: s = 0.1_real32
real(real64) :: d = 0.1_real64
write (*, '(a, es26.17e3)') 'real32 0.1 = ', s
write (*, '(a, es26.17e3)') 'real64 0.1 = ', d
write (*, '(a, l1)') '0.1 + 0.2 == 0.3 (real64): ', 0.1_real64 + 0.2_real64 == 0.3_real64
write (*, '(a, es26.17e3)') '0.1 + 0.2 - 0.3 = ', 0.1_real64 + 0.2_real64 - 0.3_real64
end program precision_demo
The single-precision value of 0.1 is 0.100000001490116119..., the
double-precision value is 0.100000000000000006.... The sum of 0.1 and 0.2 is
not equal to 0.3 in double precision either; the difference is about
5.55e-17. For that reason real numbers are never compared with
==: use a tolerance, as in abs(a - b) < 1.0e-9.
$ gfortran precision.f90 -o precision $ ./precision real32 0.1 = 1.00000001490116119E-001 real64 0.1 = 1.00000000000000006E-001 0.1 + 0.2 == 0.3 (real64): F 0.1 + 0.2 - 0.3 = 5.55111512312578270E-017
Choosing a kind by requirements
The inquiry functions selected_int_kind(r) and
selected_real_kind(p, r) return the smallest kind that can hold
integers of up to r decimal digits, or reals with at least
p decimal digits and an exponent range of at least
r. They state the requirement and let the compiler find the kind.
When no kind is available the result is -1.
program selected
implicit none
integer, parameter :: i9 = selected_int_kind(9)
integer, parameter :: i18 = selected_int_kind(18)
integer, parameter :: i19 = selected_int_kind(19)
integer, parameter :: r6 = selected_real_kind(6)
integer, parameter :: r15 = selected_real_kind(15, 300)
integer, parameter :: r30 = selected_real_kind(30)
integer, parameter :: r40 = selected_real_kind(40)
print *, 'selected_int_kind(9): ', i9
print *, 'selected_int_kind(18): ', i18
print *, 'selected_int_kind(19): ', i19
print *, 'selected_real_kind(6): ', r6
print *, 'selected_real_kind(15, 300): ', r15
print *, 'selected_real_kind(30): ', r30
print *, 'selected_real_kind(40): ', r40
end program selected
Nine digits fit in kind 4, 18 digits in kind 8, and 19 digits need kind 16, a
128-bit integer that gfortran provides on this platform. A real with 6 digits is
kind 4, one with 15 digits and an exponent range of 300 is kind 8, and 30
digits need the 128-bit kind 16. There is no kind with 40 digits, so the last
call returns -1. The usual pattern is
integer, parameter :: dp = selected_real_kind(15, 307).
$ gfortran selected.f90 -o selected $ ./selected selected_int_kind(9): 4 selected_int_kind(18): 8 selected_int_kind(19): 16 selected_real_kind(6): 4 selected_real_kind(15, 300): 8 selected_real_kind(30): 16 selected_real_kind(40): -1
Complex and logical values
A complex value is a pair of reals. It is written as a pair in
parentheses, and the functions real and aimag return
the two parts. Arithmetic, abs (the magnitude) and the other
mathematical functions work on complex values directly. A logical
has only two values, and the operators .and., .or.,
.not., .eqv. and .neqv. combine them.
program complexlogical
implicit none
complex :: z
logical :: a, b
z = (3.0, 4.0)
print *, 'z =', z
print *, 'real part:', real(z), ' imaginary part:', aimag(z)
print *, 'abs(z) =', abs(z)
print *, 'z * z =', z * z
a = .true.
b = .false.
print *, a .and. b, a .or. b, .not. a, a .eqv. b, a .neqv. b
end program complexlogical
The product of 3 + 4i with itself is -7 + 24i, and
its magnitude is 5. The last line prints five logical values, shown as
T and F: .true. .and. .false. is false,
the .or. is true, .not. of true is false, and the
last two columns show that equivalence is false and non-equivalence is true for
two different values.
$ gfortran complexlogical.f90 -o complexlogical $ ./complexlogical z = (3.00000000,4.00000000) real part: 3.00000000 imaginary part: 4.00000000 abs(z) = 5.00000000 z * z = (-7.00000000,24.0000000) F T F F T
Characters
A character variable has a fixed length given with
len=. A shorter value is padded with blanks on the right, and a
longer value is cut off. The function len returns the declared
length and len_trim the length without trailing blanks. A variable
declared with character(len=:), allocatable takes the length of
whatever is assigned to it.
program chars
implicit none
character(len=10) :: padded
character(len=3) :: short
character(len=:), allocatable :: flexible
padded = 'Fortran'
short = 'Fortran'
flexible = 'Fortran'
print *, '[', padded, ']'
print *, 'len:', len(padded), ' len_trim:', len_trim(padded)
print *, '[', short, ']'
print *, '[', flexible, ']'
print *, 'len:', len(flexible)
end program chars
The variable padded has 10 characters; the seven letters are
followed by three blanks, which the brackets in the output make visible, and
len_trim reports 7. short has room for three
characters, so only For is stored, and gfortran warns about the
truncation at compile time. The allocatable variable adjusts to 7 characters.
$ gfortran -Wall chars.f90 -o chars
chars.f90:8:21:
8 | short = 'Fortran'
| 1
Warning: CHARACTER expression will be truncated in assignment (3/7) at (1) [-Wcharacter-truncation]
$ ./chars
[Fortran ]
len: 10 len_trim: 7
[For]
[Fortran]
len: 7
Type conversion
Arithmetic between different types converts the operand of the lower type to
the higher one, in the order integer, real, complex. For two reals of different
kinds, the result has the larger kind. Dividing two integers is an integer
division, which truncates; one of the operands must be converted explicitly
to get a fractional result. The functions int, real,
nint, floor and ceiling convert real
numbers to integers in different ways.
program convert
use, intrinsic :: iso_fortran_env, only: real64
implicit none
integer :: i = 7, j = 2
real :: r = 7.0
real(real64) :: d = 2.0_real64
print *, 'i / j = ', i / j
print *, 'real(i) / j = ', real(i) / j
print *, 'r / j = ', r / j
print *, 'kind(r + d) = ', kind(r + d)
print *, 'int(3.99) = ', int(3.99), ' int(-3.99) =', int(-3.99)
print *, 'nint(3.5) = ', nint(3.5), ' nint(-3.5) =', nint(-3.5)
print *, 'floor(-3.5) = ', floor(-3.5), ' ceiling(-3.5) =', ceiling(-3.5)
end program convert
7 / 2 is 3 for integers and 3.5 as soon as one operand is real.
Mixing a default real with a 64-bit real gives a result of kind 8. The
conversions of -3.5 and 3.99 show the difference between the functions:
int truncates toward zero, nint rounds to the nearest
integer with halves away from zero, floor rounds toward minus
infinity, and ceiling toward plus infinity.
$ gfortran convert.f90 -o convert $ ./convert i / j = 3 real(i) / j = 3.50000000 r / j = 3.50000000 kind(r + d) = 8 int(3.99) = 3 int(-3.99) = -3 nint(3.5) = 4 nint(-3.5) = -4 floor(-3.5) = -4 ceiling(-3.5) = -3
Next steps
The literals and constants article shows how to write values of a given kind, including the suffix syntax used above. For declarations and constants, see Fortran variables and declarations.
Source
GNU Fortran: the KIND intrinsic
GNU Fortran: the SELECTED_REAL_KIND intrinsic
GNU Fortran: the ISO_FORTRAN_ENV module
In this article we have looked at the five intrinsic types, the meaning of
kinds, the kind constants of iso_fortran_env, the limits of
integers and reals, the representation error of floating-point numbers, and
type conversions. The previous article,
Fortran variables and declarations, covers
how to declare them, and the next one,
Fortran literals and constants, covers how
to write their values.
Author
List all Fortran tutorials.