6

Is it possible to obtain more than 16 digits with double precision without using quadruple? If it is possible, does it depend on compiler or something else? Because I know someone said he was working with double precision and had 22 digit precision.

user207421
  • 305,947
  • 44
  • 307
  • 483
Shibli
  • 5,879
  • 13
  • 62
  • 126

2 Answers2

7

The data type double precision stems from Fortran 77, and the only requirement for that type is that is has more precision than real. You shouldn't use that any more.

In Fortran 90/95 and beyond, at least two sizes of real numbers are supported. The precision is determined by the kind parameter, of which the value depends on the compiler.

real(kind=8) :: a, b

To have a portable way of defining precision, you can obtain a kind value that allows a certain precision by using:

integer, parameter :: long_double = SELECTED_REAL_KIND(22)

then you can declare your variables as

real(kind=long_double) :: a, b

but it is not certain your compiler will support that precision, in which case the SELECTED_REAL_KIND function will return a negative number.

see also this post

Community
  • 1
  • 1
steabert
  • 6,540
  • 2
  • 26
  • 32
  • But you wrote `integer`. Could only `integer` has 22 digits not `double`? – Shibli Feb 09 '12 at 12:53
  • `long_double` is an integer which is used to indicate the `kind` of the `real` variables `a` and `b` such that they have at least precision 22 – steabert Feb 09 '12 at 13:05
  • 2
    @Shibli It is also often useful to get the kinds of single and double precision floats on your system in portable way. For this one can use `integer, parameter :: sp=kind(1.e0)` and `integer, parameter :: dp=kind(1.d0)`. You can then declare a double precision float as `real(kind=dp) :: double`. – Chris Feb 09 '12 at 13:08
  • 1
    F2003 also suppots `use iso_fortran_env; real(kind=real64) :: foo`. intel v12 already supports this... – Jonathan Dursi Feb 09 '12 at 13:15
  • 2
    @Chris Note that 1.e0 or 1.d0 will be converted at compile time if a precision flag is specified, e.g. -r4 or -r8 for ifort. So your suggestion works only if such flag is not specified. – milancurcic Feb 09 '12 at 15:35
  • @IRO-bot Good point - never thought of this since I don't use those flags myself. So what is the best way to specify single and double precision floats? For my system it would be `float32 = selected_real_kind(6, 37)` and `float64 = selected_real_kind(15, 307)` - is this pretty portable? – Chris Feb 09 '12 at 16:55
5

As the first answer states, the most portable way is to specify the precision of number is to use the intrinsic functions. The design concept of the language is that you figure out what precision is required for your calculation and request it, and the compiler provides that precision or better. E.g., if you calculate that your differential equation solution is stable with 11 decimal figures, then you request this value and the compiler provides its best type meeting your requirement. This is a foreign approach to most programmers, who are used to thinking about what the few choices provided by hardware rather than what they need, and maybe not so easy since few of us are numerical analysts.

If you want to use the SELECTED_REAL_KIND intrinsic and optimize for your particular compiler and hardware, you may wish to experiment. Some combinations will provide quadrupole precision in software, which will be slow. A compiler that has double precision and 10-byte extended precision will provide that longer type via selected_real_kind (17). A compiler that has double precision and quadruple precision but not 10-byte extended precision will provide quadrupole precision via selected_real_kind (17) or selected_real_kind (32). (I'm not aware of any compiler that supports both 10-byte extended and quadrupole.) The compiler that lacks quadrupole precision will return -1 for selected_real_kind (32).

M. S. B.
  • 28,968
  • 2
  • 46
  • 73