带有ifort的指数的Fortran运算符优先级错误

Wil*_*son 6 fortran operator-precedence intel-fortran

在评估带有指数后跟乘法的简单表达式时,我在Portland和英特尔fortran编译器之间得到了不同的行为.我很确定pgf90(和gfortran)根据我对运算符优先级的理解而正常工作,但我想要第二个意见,因为这些事情可能会有点棘手.

这是我的代码简化为一个非常基本的形式.当使用ifort运行时,表单的表达式将被ifort d1=a**-2*b解释为pgf90和gfortran.如果我从指数中删除负号,则所有三个编译器都将其解释为.如果我将*b改为+ b,我也会从这三个中获得良好的行为.d1=a**(-2*b)d1=(a**-2)*bd1=(a**2)*b

program badvals
  implicit none
  real :: a, b, c1, c2, d1, d2

  a = 2.
  b = 4.

  ! Works with addition following the exponent.
  c1 = a**-2+b
  c2 = a**(-2)+b

  ! Ifort differs with multiplication following negative exponent.
  d1 = a**-2*b
  d2 = a**(-2)*b

  print*, "c1, d1       = ",c1, d1
  print*, "c2, d2       = ",c1, d2
  print*, "c2-c1, d2-d1 = ",c2-c1, d2-d1
end program badvals

!Program output for ifort v13.0.1.117: (either -O0 or -fast):
! c1, d1       =    4.250000      3.9062500E-03
! c2, d2       =    4.250000       1.000000
! c2-c1, d2-d1 =   0.0000000E+00  0.9960938

!Program output for pgf90 v12.10-0: (either -O0 or -fast):
! c1, d1       =     4.250000        1.000000
! c2, d2       =     4.250000        1.000000
! c2-c1, d2-d1 =     0.000000        0.000000

!Program output for gfortran v4.1.2: (either -O0 or -O3):
! c1, d1       =    4.250000       1.000000
! c2, d2       =    4.250000       1.000000
! c2-c1, d2-d1 =    0.000000       0.000000
Run Code Online (Sandbox Code Playgroud)

这些差异背后是否有历史,因此它们应被视为"特征"?或者,这是英特尔的一个彻头彻尾的错误吗?

M. *_* B. 5

搜索网络时,我发现不允许连续两个运营商的声明.因此,解释而不是拒绝这个表达是语言的扩展.不同编译器供应商对该扩展的实现方式不同.

实际上,当我使用带有限制性编译器选项的gfortran时,它会拒绝这个代码示例:

badvals.f90:9.11:
  c1 = a**-2+b
           1
Error: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
badvals.f90:13.11:

  d1 = a**-2*b
           1
Error: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
Run Code Online (Sandbox Code Playgroud)

同样,具有限制性编译器选项的ifort提供以下内容:

badvals.f90(9): warning #7026: Non-standard extension
  c1 = a**-2+b
----------^
badvals.f90(13): warning #7026: Non-standard extension
  d1 = a**-2*b
----------^
Run Code Online (Sandbox Code Playgroud)

所以:1)使用编译器的警告和错误选项可能非常有帮助,2)它更多的是扩展而不是bug,3)即使这个表达式被语言允许,gfortran的建议也很好 - 使用括号即使不需要也要清晰.

  • "不允许两个连续的运算符"需要一点资格 - 它适用于这里因为二级表达式(算术的)的语法规则,但通常不是......`to_be .or..不.to_be`是好的(在莎士比亚Fortran中很常见),你也可以在那里找到一个定义的一元运算符.如果OP想要扩展的正式描述,他们可以阅读[this](http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-win/GUID- A03254E4-36D6-4CFC-9DF6-AD264BB6C820.htm). (3认同)