在评估带指数然后乘以的简单表达式时,波特兰和Intel fortran编译器之间的行为有所不同。根据我对运算符优先级的理解,我非常确定pgf90(和gfortran)可以正常工作,但是我想提出第二个意见,因为这些事情可能会有些棘手。

这是我的代码简化为非常基本的形式。当与ifort一起运行时,格式d1=a**-2*b的表达式由pgf90和gfortran的ifort解释为d1=a**(-2*b)。如果我从指数中删除负号,则所有三个编译器都将此解释为d1=(a**-2)*b。如果我将* b更改为+ 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


这些差异背后是否有历史,因此应将其视为“功能”?或者,这是英特尔方面的彻底错误吗?

最佳答案

在网上搜索时,我发现该声明不允许连续两个运算符。因此,解释而不是拒绝该表达是语言的扩展。该扩展已由不同的编译器供应商以不同的方式实现。

确实,当我将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)


同样,具有限制性编译器选项的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
----------^


所以:
1)使用编译器的警告和错误选项可能会非常有帮助,
2)它不仅仅是错误,是扩展,
3)即使语言允许使用此表达式,gfortran的建议也很好-即使不需要,也请使用括号以保持清楚。

08-17 04:22