0

I use Visual Studio (2010 SP1) with Fortran IMSL (2011) and I can't get the right precision for my reals:

program prova

use, intrinsic :: iso_fortran_env

implicit none

integer, parameter :: ikind=selected_real_kind(p=8, r=99)
real(kind=ikind) ::      a=0.79
real(real64) ::          b=0.79
real(kind=16) ::         c=0.79
real(8) ::               d=0.79

print *, a
print *, b
print *, c
print *, d

end program prova

give me the same result: 0.790000021457672 (one with more precision, one with less precision but every number is different from the assigned one: 0.79)

Why my willingness is not respected?

How can I set all reals to the needed precision?

NB: my problem has nothing to do with the "limited nature of computer", roundoff numbers and similar. my problem regards type/kind of variable in Fortran.

mattia.b89
  • 111
  • 8

1 Answers1

1

You are setting the variables to have the desired precision, but then assign constants with default precision. Try:

program prova

use, intrinsic :: iso_fortran_env

implicit none

integer, parameter :: ikind=selected_real_kind(p=8, r=99)
real(kind=ikind) ::      a=0.79_ikind
real(real64) ::          b=0.79_real64
real(kind=16) ::         c=0.79_16
real(8) ::               d=0.79_8

print *, a
print *, b
print *, c
print *, d

end program prova

This will set the constants in the correct precision, but since you only provide two significant digits, the result will still be rounded to the nearest representable floating point number (in base 2). 0.79 can be represented exactly in the decimal system (base 10), but not in base 2. Hence the deviations. You should read the Wikipedia Artical on Floating-Point Numbers and, of course, What Every Computer Scientist Should Know About Floating-Point Arithmetic.

This results in

  0.79000000000000004     
  0.79000000000000004     
  0.790000000000000000000000000000000031      
  0.79000000000000004   

on my machine.

Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
  • OK, today I learnt something new! Anyway this forces me change my code, all my source. Is there a way to declare all real with a wanted precision? – mattia.b89 Jun 14 '15 at 09:49
  • Yes, you can do that with most compilers. For `gfortran`, this is done with `-freal-XX-real-YY` [see here](https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html). For other compilers, equivalent directives exist. But I personally would recommend to stick with the explicit declaration. This is Standard-conforming and supported by all major compilers. It is also simpler to read and less error-prone. – Alexander Vogt Jun 14 '15 at 10:04
  • another doubt before close this question: do you prefer to explicitly set precision even if you have to handle big arrays of data; e.g. array of molar weight of 100 compound? – mattia.b89 Jun 14 '15 at 11:54
  • Yes, I do. The added text outweighs potential errors due to missing precision by far. – Alexander Vogt Jun 14 '15 at 12:08