Exponentiation in Fortran/gfortran to high precision

时光总嘲笑我的痴心妄想 提交于 2021-01-28 04:45:34

问题


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

  1. 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

  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!