How can I get the same results with floating-point arithmetic using different compilers and possibly also different computers?
This is p.f90
program fl
implicit none
real(kind=8) :: a
a=9d0/10d0
write(*,*) a
end program
With gfortran -o p p.f90 I get 0.90000000000000002
With ifort -g -o p p.f90 I get 0.900000000000000
Is there a way to achieve consistency? The small things propagate and become larger.
Best regards Alessandro
In computing, floating-point arithmetic (FP) is arithmetic using formulaic representation of real numbers as an approximation to support a trade-off between range and precision.
gfortran auto-vectorization isn't implied until -O3, while ifort -O2 implies it. auto-vectorization of sum reductions generally improves accuracy, more so with ifort than with gfortran, as ifort uses more partial sums. The options quoted above turn off vector sum reduction for both compilers.
Floating-Point Exceptions and Fortran In general, a message results if any one of the invalid, division-by-zero, or overflow exceptions have occurred. Inexact exceptions do not generate messages because they occur so frequently in real programs.
We'll turn to floating-point arithmetic below, but let me deal first with a misconception you have. Your use of list-directed formatting in the write statement means that the format chosen by the compiler to write out a variable is, well, the compiler's choice; it's not mandated by the language standard. Your use of the second *
in write(*,*)
tells the compiler to write out the value of a variable as it wishes. So what you have is not evidence that there is something wrong with the arithmetic, but that there are differences between gfortran
and ifort
. If I modify your write statement to
write(*,'(f21.18)') a
then my Intel Fortran program writes
0.900000000000000022
to the console.
SO is littered with questions arising from unfamiliarity with the details of floating-point arithmetic so I'm not going to write a treatise, just a few observations relevant to your question.
IEEE-754 64-bit floating-point numbers (which is probably what you get with the declaration real(kind=8)
) only provide approximately 16 decimal digits of useful information. Actually, since they're binary and there is no easy correspondence between the number of digits in one base and in another, it's actually 15.95 decimal digits and many users round this down and never look at anything after the 15th significant figure in a floating-point number's decimal representation. So both ifort
and gfortran
are misleading you with their trailing 2
s.
IEEE-754 defines not only the formats for f-p numbers, but also some rules for rounding and for arithmetic operations. A carefully-written program which uses only those arithmetic operations (I think square root is also specified) and which takes care about rounding modes and rounding operations should produce the same results on two different processors. Of course, not many useful numerical programs confine themselves to the basic arithmetic operations.
Since the 2003 standard Fortran has included an intrinsic module called ieee_arithmetic
which gives the programmer direct access to the underlying IEEE-754 capabilities of the hardware on which it is running -- but note that it does not require that the hardware have any such capabilities. Using ieee_arithmetic
and another intrinsic module called ieee_exceptions
you should, if your hardware provides the necessary support, be able to write programs which compile under both gfortran
and ifort
and which produce, when executed, the same results to the last bit of every f-p number.
You'll also need to familiarise yourself with the optimisation options and numerical arithmetic options of the compiler(s) you're using. Most compilers have an option whose meaning is sacrifice IEEE compliance for speed
(for ifort
I think it's fp-model
). In general adherence to IEEE-754 for operations will slow your programs.
You cannot.
See under Systems Aspects in What Every Computer Scientist Should Know About Floating-Point Arithmetic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With