Search code examples
fortranprecisionfortran90

Will I get more accuracy in Fortran with `real(wp)`?


Have I got more accuracy in my code by replacing all :

real(dl) variable1

by putting at the beginning of each Fortran90 source files :

integer, parameter :: wp = selected_real_kind(15,307)

and declare variable like this :

real(wp) variable1

Update 1

You are right, a simple program gives :

program  main

  implicit none

  integer, parameter :: dl = KIND(1.d0)
  integer, parameter :: wp = selected_real_kind(15,307)
  real(kind=dl) :: dl_number
  real(kind=wp) :: wp_number

  write(*,*) 'epsilon for dl number', epsilon(dl_number)
  write(*,*) 'precision for dl number', precision(dl_number)
  write(*,*) 'epsilon for wp number', epsilon(wp_number)
  write(*,*) 'precision for wp number', precision(wp_number)

  stop

end

And the output :

epsilon for dl number   2.2204460492503131E-016
 precision for dl number          15
 epsilon for wp number   2.2204460492503131E-016
 precision for wp number          15

So there is no need to use wp = selected_real_kind(15,307) instead of dl = KIND(1.d0).


Solution

  • In general no.

    There are two issues:

    1. Is wp of higher precision that dl ? This depends on the compiler and platform.

    2. Is the numerical result improved by the increase in accuracy of the floating point numbers? In some case, the accuracy is limited by the algorithm or the data and you don't get anything from this except a slower program.

    As a first diagnosis, anyway, execute

    write(*,*) 'dl =', dl
    write(*,*) 'wp =', wp
    

    to see whether the kinds are actually the same.

    Then, you can obtain some information about the kinds:

    real(kind=dl) :: dl_number
    real(kind=wp) :: wp_number
    
    write(*,*) 'epsilon for dl number', epsilon(dl_number)
    write(*,*) 'precision for dl number', precision(dl_number)
    write(*,*) 'epsilon for wp number', epsilon(wp_number)
    write(*,*) 'precision for wp number', precision(wp_number)
    

    epsilon returns the smallest representable number for the kind, and precision the decimal precision.

    You should anyway have an idea of what accuracy is required for your computation and work from that.

    As pointed out by albert and Ian Bush, there are many other places in the code where you need to check out the issue of numerical representation.

    • Literal constants need special care. 1.0/3.0 and 1._wp/3._wp have significantly different values for instance.
    • Some functions will also return default real value (i.e. single precision) unless requested, such as the real intrinsic.
    • ...