Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Floating point Fortran/gfortran中的高精度幂运算_Floating Point_Fortran_Gfortran_Exponentiation - Fatal编程技术网

Floating point Fortran/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

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编译

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 $ 
因此

  • 看起来编译器足够聪明,可以通过乘法计算整数幂,这比一般的幂函数快得多

  • 使用一般的求幂函数与乘法答案仅相差1位。鉴于我们不能说哪一个本身更准确,我们必须接受两者同样准确


  • 因此,总的来说,编译器在可能的情况下使用简单的乘法,而不是一个完整的求幂例程,但即使它必须使用更昂贵的方法,它也会给出相同的答案,出于完整性考虑,“相同”一词的含义,对(精确的)分数求幂会导致

    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