如果我要使用嵌套括号计算多项式,那么单独声明每个常量并将它们声明为数组之间是否存在差异?
例如,
之间是否有区别?real(kind = c_double), parameter :: &
P0 = .5, &
P1 = .8, &
P2 = -.1, &
P3 = -.7, &
P4 = -.4, &
P5 = -.6, &
P6 = -.2
并计算
x = ((((((P6 * a + P5) * a + P4) * a + P3) * a + P2) * a + P1) * a + P0)
或
real(kind = c_double), parameter, dimension(7) :: P = &
[.5, .8, -.1, -.7, -.4, -.6, -.2]
并计算
x = ((((((P(7) * a + P(6)) * a + P(5)) * a + P(4)) * a + P(3)) * a + P(2)) * a + P(1))
答案 0 :(得分:5)
是的,存在差异,但这些差异并不是您在此处使用的重要差异。
差异来自于给出(与问题略有不同)声明的事实
real, parameter :: P1=0.1, P2=0.2, P(2)=[0.1,0.2]
P1
和P2
是常量,但P(1)
和P(2)
不是。 P
是常数,但这不是一回事。因此,P1
可能会在某些P(1)
无法使用的情况下使用。
然而,在像
这样的表达式中((((((P6 * a + P5) * a + P4) * a + P3) * a + P2) * a + P1) * a + P0)
恒定性质并不重要,P
的元素可以在那里轻松使用。
在文字常量中复杂的文字常量和(对于整数)种类参数的情况下会出现差异。此外,如果P(1)
是数组元素,则可以在某些方面使用它,不适合P1
。
我会注意到这个问题的一些特定内容:
P0
,可以从0
索引数组:real, parameter, dimension(0:6) :: P=[...]
; real, parameter, dimension(0:*) :: P=[...]
答案 1 :(得分:1)
我想指出,在关于常量表达式的部分中,标准说
常量表达式是......
(1)常数的常数或子对象。
那么在P1
无法使用的地方P(1)
可以使用哪个地方?当然P(1)
可以在P1
无法使用的地方使用program polyval
use ISO_C_BINDING, only:C_DOUBLE
implicit none
integer, parameter :: wp = C_DOUBLE
real(wp), parameter :: P(0:*) = &
[0.5_wp,0.8_wp,-0.1_wp,-0.7_wp,-0.4_wp,-0.6_wp,-0.2_wp]
real(wp) a, x
integer i
a = 10
x = sum([(a**i*P(i),i=0,ubound(P,1))])
write(*,*) x
end program polyval
。
数组方法在我看来真的很有吸引力,因为理解数组表达式要容易得多 - 读者可能会错过嵌套表达式中的一些不规则性,但数组公式中没有:
function poly1(x)
use ISO_FORTRAN_ENV, only: wp=> REAL64
real(wp) x
real(wp) poly1
real(wp), parameter :: P0 = 0.5_wp, P1 = 0.8_wp, P2 = -0.1_wp, &
P3 = -0.7_wp, P4 = -0.4_wp, P5 = -0.6_wp, P6 = -0.2_wp
poly1 = (((((P6*x+P5)*x+P4)*x+P3)*x+P2)*x+P1)*x+P0
end function poly1
编辑:我认为到目前为止Fortran编译器可能足够聪明,可以识别上面用于多项式评估的习语,但显然我错了。我原以为是
function poly2(x)
use ISO_FORTRAN_ENV, only: wp=> REAL64
real(wp) x
real(wp) poly2
real(wp), parameter :: P(0:6) = &
[0.5_wp,0.8_wp,-0.1_wp,-0.7_wp,-0.4_wp,-0.6_wp,-0.2_wp]
integer i
poly2 = sum([(x**i*P(i),i=0,ubound(P,1))])
end function poly2
和
gfortran -S -O3 -ffast-math -funroll-loops poly2.f90
会产生类似的代码,但ifort /Fa /c /fast /Qipo- poly2.f90
和x
计算DOT_PRODUCT
和有效program test2
use ISO_FORTRAN_ENV, only:wp=>REAL64
implicit none
complex(wp) x
real(wp), parameter :: P1 = 4*atan(1.0_wp)
real(wp), parameter :: P(1) = exp(1.0_wp)
x = (P1,0)
write(*,*) x
! x = (P(1),0) ! Fails because literal or named constant is required
write(*,*) x
end program test2
的权力,而不是使用有效的方法。因此,可能需要像汇编而不是高级语言一样写出表达式,以在此上下文中获得合理的性能。
编辑:好的,所以似乎有一个上下文可以使用REAL命名常量,但REAL常量表达式不能。
module mymod
use ISO_FORTRAN_ENV,only:wp=>REAL64
implicit none
contains
subroutine sub(x)
real(wp) x(*)
write(*,*) x(1)
end subroutine sub
end module mymod
program test3
use mymod
implicit none
real(wp), parameter :: P1 = 4*atan(1.0_wp)
real(wp), parameter :: P(1) = exp(1.0_wp)
! call sub(P1) ! Fails because array actual argument required
call sub(P(1)) ! Succeeds due to sequence association
end program test3
但是搜索标准我认为这是唯一的情况。在f2003中,在 complex-literal-constant 中首次允许使用命名常量吗?为了完整性,我提供了一个示例,其中常量表达式可以起作用,但不是命名常量:
{{1}}