Fortran
  • Learn
  • Compilers
  • Community
  • Packages
  • News
  • Discourse
  • Twitter
  • Github
  • RSS Feed
Back to Learn Fortran index

Fortran Best Practices

  • Introduction
  • Fortran Style Guide
  • Floating Point Numbers
    • Integer Division
    • Modules and Programs
    • Arrays
    • Multidimensional Arrays
    • Element-wise Operations on Arrays
    • Allocatable Arrays
    • File Input/Output
    • Callbacks
    • Type Casting in Callbacks

    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.

    Back

    Next

    Learn · Compilers · Community · Packages · News
    This site's source is hosted on GitHub.