在评估带有指数后跟乘法的简单表达式时,我在Portland和英特尔fortran编译器之间会遇到不同的行为。我很确定pgf90(和gfortran)是基于我对运算符优先级的理解而正常工作的,但是我想要第二个意见,因为这些事情可能会有点棘手。
这是我的代码简化为一个非常基本的形式。当使用ifort运行时,表单d1=a**-2*b
的表达式被{0}解释为d1=a**(-2*b)
由pgf90和gfortran解释为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
这些差异背后是否存在历史,因此应将其视为“功能”?或者,这是英特尔的一个彻头彻尾的错误吗?
答案 0 :(得分: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)
同样,具有限制性编译器选项的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)它更像是一个扩展而不是一个bug, 3)即使语言允许这个表达,gfortran的建议也是好的 - 即使不是必需的,也要使用括号来表示清晰。