Fortran 分配给复杂变量时括号出错
我的Fortran代码中有以下命令集:Fortran 分配给复杂变量时括号出错,fortran,Fortran,我的Fortran代码中有以下命令集: COMPLEX*16, DIMENSION(4,1) :: INSTATE_BASISSTATES INSTATE_BASISSTATES(:,:) = (0.0D0,0.0D0) INSTATE_BASISSTATES(1,1) = ((1.0D0/SQRT(2)),0.0D0) INSTATE_BASISSTATES(3,1) = ((1.0D0/SQRT(2)),0.0D0) 当我在cygwin上使用gfortran运行/编译程序时,我得到
COMPLEX*16, DIMENSION(4,1) :: INSTATE_BASISSTATES
INSTATE_BASISSTATES(:,:) = (0.0D0,0.0D0)
INSTATE_BASISSTATES(1,1) = ((1.0D0/SQRT(2)),0.0D0)
INSTATE_BASISSTATES(3,1) = ((1.0D0/SQRT(2)),0.0D0)
当我在cygwin上使用gfortran运行/编译程序时,我得到了错误
INSTATE_BASISSTATES(1,1) = (1.0D0/DREAL(SQRT(2.0D0)),0.0D0)
1
Error: Expected a right parenthesis in expression at (1)
INSTATE_BASISSTATES(3,1) = (1.0D0/DREAL(SQRT(2.0D0)),0.0D0)
1
Error: Expected a right parenthesis in expression at (1)
可能是什么问题?我的括号不正确吗?这确实是“出于设计”,可以先定义感兴趣的常数,然后在初始化中使用它。例如:
COMPLEX*16, DIMENSION(4,1) :: INSTATE_BASISSTATES
REAL*8, PARAMETER :: my_const = 1D0 / SQRT(2D0)
INSTATE_BASISSTATES(:,:) = (0.0D0,0.0D0)
INSTATE_BASISSTATES(1,1) = (my_const,0.0D0)
INSTATE_BASISSTATES(3,1) = (my_const,0.0D0)
但是,语句
REAL*8,PARAMETER::my_const=1D0/SQRT(2D0)
似乎至少需要Fortran2003标准,否则,将产生以下错误元素函数作为带有非整数/非字符参数的初始化表达式。可以使用gfortran和-std=f2003
指定标准,尽管默认情况下它可能处于活动状态。在赋值语句的右侧,您试图使用复杂的文字常量。但是,
(1.0D0/DREAL(SQRT(2.0D0)),0.0D0)
不是这样一个常量的有效形式
对于复杂文字,实部和虚部必须是命名常量或文字常量1.0D0/DREAL(SQRT(2.0D0))
都不是这些东西。对于没有投诉的行,(0.0D0,0.0D0)
的两个组件都是文字常量
如中所示,您可以使用所需的值创建一个命名常量并使用它。或者,由于您只是在做一个枯燥的赋值(没有适用于初始化等的各种限制),您可以使用cmplx
内在函数来返回一个复杂值
INSTATE_BASISSTATES(1,1) = CMPLX(1.0D0/DREAL(SQRT(2.0D0)),0.0D0)
这里实部和虚部不需要是常数。你甚至可以注意到
INSTATE_BASISSTATES(1,1) = CMPLX(1.0D0/DREAL(SQRT(2.0D0)))
同样有效:如果未提供虚部值,则返回的复数具有虚部零
不过有一点复杂<默认情况下,code>cmplx
返回一个带有默认实数类型的复数。要返回匹配complex*16
(这不是标准Fortran,但让我们假设它对应于双精度
)的内容,您需要CMPLX(…,[…],KIND=KIND(0d0)
)(或KIND=KIND(INSTATE\u BASISSTATES)
)
作为旁注,弗拉基米尔F的评论
dreal
不是标准的Fortran。您可以将dble
或real
与适当的种类号一起使用。但是我们也可以看到,sqrt(2d0)
已经返回了一个双精度实数,所以即使是那些都是多余的:1/sqrt(2d0)
与原来更麻烦的表达式具有相同的(数学)结果。正如2d0**(-0.5)
和sqrt(2d0)/2
一样
您甚至可以将右侧替换为
SQRT((5d-1,0))
正如我们看到的,
sqrt
也接受一个复杂的参数(在本例中是一个复杂的文本常量)。这种形式还避免了kind=
说明符的尴尬:它的值既有参数的种类,也有参数的类型。@J123仍然没有回答这个紧迫的问题。您是使用.f
扩展名以固定格式编写代码,还是使用自由格式.f90
?另外,您使用的是什么版本的gfortran?我在下面发布了一个完整的修复程序。您可以使用命名的参数
常量,或作为内在转换函数cmplx
的返回值,通过直接赋值对数组进行叶化。请注意,kind
参数wp
可以自由使用来控制浮点精度
program main
use iso_fortran_env, only: &
wp => REAL64, & ! Or REAL128 if your architecture supports it
compiler_version, &
compiler_options
! Explicit typing only
implicit none
! Variable declarations
complex(wp) :: instate_basisstates(4,1)
real (wp), parameter :: ZERO = 0 ! Assigning integers is safe
real (wp), parameter :: SQRT2 = sqrt(2.0_wp)
real (wp), parameter :: ONE_OVER_SQRT2 = 1.0_wp/SQRT2
! Executable statements
instate_basisstates(:,:) = ZERO
instate_basisstates(1,1) = (ONE_OVER_SQRT2, ZERO)
instate_basisstates(3,1) = cmplx(1.0_wp/sqrt(2.0_wp), 0.0_wp, kind=wp)
print '(/4a/)', &
'This file was compiled using ', compiler_version(), &
' using the options ', compiler_options()
end program main
这将产生:
This file was compiled using GCC version 6.1.1 20160802 using the options -mtune=generic -march=x86-64 -O3 -Wall -std=f2008ts
试着用
DSQRT
@Jean Françoisfare来改变SQRT
,这永远不是一个解决方案,我无法想象有什么问题可以解决。DSQRT和其他数据函数在FORTRAN 77问世近40年后就不再有用了。下次我会让编译器准备好测试,而不是告诉未检查的东西。顺便说一句,DREAL不是标准FORTRAN。我建议你不要用它。只需使用REAL
。或者可能是DBLE
。很抱歉,我不明白应该如何根据您的建议调整我的程序。请务必让我知道。谢谢。我仍然收到错误:`REAL*8,PARAMETER::my_const=1.0D0/SQRT(2D0)1错误:语句标签中的非数字字符位于(1)`和`REAL*8,PARAMETER::my_const=1.0D0/SQRT(2D0)1错误:不可分类语句位于(1)`和`INSTATE_基本状态(1,1)=(my_const,0.0D0)1个错误:在(1)处的表达式中应为右括号,`INSTATE_BASISSTATES(3,1)=(my_const,0.0D0)1个错误:在(1)处的表达式中应为右括号,`我仍然会收到错误:REAL*8,参数::my_const=1.0D0/SQRT(2D0)1错误:语句标签中的非数字字符位于(1)
和REAL*8,参数::my_const=1.0D0/SQRT(2D0)1错误:不可分类语句位于(1)
和不稳定基本状态(1,1)=(my_const,0.0D0)1错误:表达式中应有右括号位于(1)
和不稳定基本状态(3,1)=(my_const,0.0D0)1错误:在(1)处的表达式中应为右括号,当我使用std=f2003时,我得到100个其他错误。错误:语句标签中的非数字字符?您使用的是固定源格式?我在括号中迷失了方向,认为DREAL
用于获取复数的实部。虽然1/sqrt(2d0)
在数学上等同于sqrt(0.5D0)
,但它不一定是数字。由于使用sqrt(0.5D0)