问题
How does gfortran handle exponentiation with a integer vs a real? I always assumed it was the same, but consider the example:
program main
implicit none
integer, parameter :: dp = selected_real_kind(33,4931)
real(kind=dp) :: x = 82.4754500815524510_dp
print *, x
print *, x**4
print *, x**4.0_dp
end program main
Compiling with gfortran gives
82.4754500815524510000000000000000003
46269923.0191143410452125643548442147
46269923.0191143410452125643548442211
Now clearly these numbers almost agree - but if gfortran handles integers and reals for exponentiation in the same way I would expect them to be identical. What gives?
回答1:
Expanding your program slightly shows what is going on:
ijb@ianbushdesktop ~/work/stack $ cat exp.f90
program main
implicit none
integer, parameter :: dp = selected_real_kind(33,4931)
real(kind=dp) :: x = 82.4754500815524510_dp
print *, x
print *, x**4
print *,(x*x)*(x*x)
print *,Nearest((x*x)*(x*x),+1.0_dp)
print *, x**4.0_dp
end program main
Compiling and running gives:
ijb@ianbushdesktop ~/work/stack $ gfortran --version
GNU Fortran (GCC) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ijb@ianbushdesktop ~/work/stack $ gfortran exp.f90
ijb@ianbushdesktop ~/work/stack $ ./a.out
82.4754500815524510000000000000000003
46269923.0191143410452125643548442147
46269923.0191143410452125643548442147
46269923.0191143410452125643548442211
46269923.0191143410452125643548442211
ijb@ianbushdesktop ~/work/stack $
Thus
It looks like the compiler is clever enough to work out that integer powers can be done by multiplies, which is much quicker than a general exponentiation function
Using the general exponentiation function is only 1 bit different from the multiplication answer. Given we can't say per se which is more accurate we must accepts both as equally accurate
Thus in conclusion the compiler uses simple multiplies where possible instead of a full blown exponentiation routine, but even if it has to use the more expensive route it gives the same answer, for carefully considered meaning of the word "same"
回答2:
For the sake of completeness, exponentiating the (exact) fraction leads to
46269923.019114341045212564354844220930226304938209797955723262974801
46269923.0191143410452125643548442211 is the nearest
46269923.0191143410452125643548442147
Exponentiating the nearest quadruple precision floating point (https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format) leads to
46269923.01911434104521256435484422112355946434320203876355837024902939447201788425445556640625
46269923.0191143410452125643548442211 does fit
So it looks like the exponentiation function did round to the nearest float. I don't know if it is luck or if the underlying math library has guaranteed correct rounding.
Integer exponentation:
x2 = x*x
x4 = x2*x2
cumulates two round off error, so it might be 1 ulp off, it's not unsurprising.
来源:https://stackoverflow.com/questions/56968179/exponentiation-in-fortran-gfortran-to-high-precision