Floating Point Numbers#
The default representation of floating point numbers is using single precision (usually 32 bits / 4 bytes). For most applications a higher precision is required. For this purpose a custom kind parameter can be defined. The recommended way of defining kind parameters is to use
integer, parameter :: dp = selected_real_kind(15)
For many purposes it also suffices to directly infer the kind parameter from a literal like here
integer, parameter :: dp = kind(0.0d0)
or to rename the imported kind parameter from the iso_fortran_env
module
use, intrinsic :: iso_fortran_env, only : dp => real64
For some insightful thoughts on kind parameters see Doctor Fortran in it takes all KINDs.
It is recommended to have a central module to define kind parameters and include them with use as necessary. An example for such a module is given with
!> Numerical storage size parameters for real and integer values
module kind_parameter
implicit none
public
!> Single precision real numbers, 6 digits, range 10⁻³⁷ to 10³⁷-1; 32 bits
integer, parameter :: sp = selected_real_kind(6, 37)
!> Double precision real numbers, 15 digits, range 10⁻³⁰⁷ to 10³⁰⁷-1; 64 bits
integer, parameter :: dp = selected_real_kind(15, 307)
!> Quadruple precision real numbers, 33 digits, range 10⁻⁴⁹³¹ to 10⁴⁹³¹-1; 128 bits
integer, parameter :: qp = selected_real_kind(33, 4931)
!> Char length for integers, range -2⁷ to 2⁷-1; 8 bits
integer, parameter :: i1 = selected_int_kind(2)
!> Short length for integers, range -2¹⁵ to 2¹⁵-1; 16 bits
integer, parameter :: i2 = selected_int_kind(4)
!> Length of default integers, range -2³¹ to 2³¹-1; 32 bits
integer, parameter :: i4 = selected_int_kind(9)
!> Long length for integers, range -2⁶³ to 2⁶³-1; 64 bits
integer, parameter :: i8 = selected_int_kind(18)
end module kind_parameter
Floating point constants should always be declared including a kind parameter suffix:
real(dp) :: a, b, c
a = 1.0_dp
b = 3.5_dp
c = 1.34e8_dp
It is safe to assign integers to floating point numbers without losing accuracy:
real(dp) :: a
a = 3
In order to impose floating point division (as opposed to integer
division 3/4
equal to 0
), one can convert the integer to a floating
point number by:
real(dp) :: a
a = real(3, dp) / 4 ! 'a' is equal to 0.75_dp
or simply separate the integer division with multiplication by 1.0_dp
real(dp) :: a
a = 3 * 1.0_dp / 4 ! 'a' is equal to 0.75_dp
To print floating point numbers without losing precision use the unlimited
format specifier (g0)
or the exponential representation (es24.16e3)
,
which will give you 17 significant digits of printout.