初始化参数序列和参数数组之间有区别吗?

时间:2017-02-05 20:42:06

标签: arrays fortran

如果我要使用嵌套括号计算多项式,那么单独声明每个常量并将它们声明为数组之间是否存在差异?

例如,

之间是否有区别?
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))

2 个答案:

答案 0 :(得分:5)

是的,存在差异,但这些差异并不是您在此处使用的重要差异。

差异来自于给出(与问题略有不同)声明的事实

real, parameter :: P1=0.1, P2=0.2, P(2)=[0.1,0.2]

P1P2是常量,但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=[...];
  • 数组的一个优点是隐含了元素的数量(在当前的Fortran,而不是F90中):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.f90x计算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}}