Floating point Fortran/gfortran中的高精度幂运算
gfortran如何处理整数与实数的幂运算?我总是假设它是一样的,但是考虑这个例子:Floating point Fortran/gfortran中的高精度幂运算,floating-point,fortran,gfortran,exponentiation,Floating Point,Fortran,Gfortran,Exponentiation,gfortran如何处理整数与实数的幂运算?我总是假设它是一样的,但是考虑这个例子: 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 使用gfortran编译 8
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
使用gfortran编译
82.4754500815524510000000000000000003
46269923.0191143410452125643548442147
46269923.0191143410452125643548442211
现在很明显,这些数字几乎是一致的——但如果gfortran以同样的方式处理整数和实数进行幂运算,我希望它们是相同的。提供了什么?稍微扩展您的程序可以显示正在发生的事情:
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
编译和运行提供:
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 $
因此
因此,总的来说,编译器在可能的情况下使用简单的乘法,而不是一个完整的求幂例程,但即使它必须使用更昂贵的方法,它也会给出相同的答案,出于完整性考虑,“相同”一词的含义,对(精确的)分数求幂会导致
46269923.019114341045212564354844220930226304938209797955723262974801
46269923.0191143410452125643548442211 is the nearest
46269923.0191143410452125643548442147
对最近的四精度浮点()求幂会导致
看来求幂函数已经四舍五入到最接近的浮点。我不知道这是运气还是底层的数学库保证了正确的舍入
整数指数:
x2 = x*x
x4 = x2*x2
累积两个舍入误差,所以可能是1 ulp off,这并不奇怪。值得注意的是,整数幂的幂运算是“数值操作数在计算表达式之前转换为结果的类型和种类”的例外。也就是说,可以看到
x**4
和x**4.
之间的差异,因为我们不需要将前者转换为后者。嗯,很有趣!所以一般来说,求幂的最佳实践是使用整数,因为它更快,并且具有相同的精度?此外,我们不得不接受两个答案同样准确,这有点令人不满意——显然其中一个更接近真实值@user1887919对于任何给定的计算,其中一个将给出更接近IEEE 754轮的结果,接近精确答案的最近值。可能没有一个通用规则来说明哪一个更准确。您可以看到gfortran使用-fdump tree-original选项做了什么。对于整数指数,将生成对_gfortran_pow_r16_i4()的调用。这是gfortran运行库的一部分。它的算法来自DeKnuth,《计算机编程的艺术》第2卷。对于浮点指数,将生成对powq()的调用。powq()是libquadmath的一部分,因此您可以阅读整型值指数是如何处理的。
x2 = x*x
x4 = x2*x2