Recursion 错误:语句函数是递归的
这是试图解决一个3*3的线性方程并打印结果,但在注释行中遇到了问题: 我在程序外部定义了模块LinearSolution,我应该在内部定义它吗?有什么区别 为什么它说语句是递归的,你知道,当我用这些语句作为普通的子例程而不是模块子例程时,它们被验证是正确的Recursion 错误:语句函数是递归的,recursion,module,fortran,fortran90,subroutine,Recursion,Module,Fortran,Fortran90,Subroutine,这是试图解决一个3*3的线性方程并打印结果,但在注释行中遇到了问题: 我在程序外部定义了模块LinearSolution,我应该在内部定义它吗?有什么区别 为什么它说语句是递归的,你知道,当我用这些语句作为普通的子例程而不是模块子例程时,它们被验证是正确的 module LinearSolution type LAE integer::N double precision,dimension(:,:),allocatable::A doub
module LinearSolution
type LAE
integer::N
double precision,dimension(:,:),allocatable::A
double precision,dimension( :),allocatable::B
contains
procedure,nopass::RowReduction
end type LAE
contains
subroutine RowReduction
double precision::C
do k=1,N
do i=k+1,N
if(A(k,k)/=0) then
C=A(i,k)/A(k,k)
B(i)=B(i)-B(k)*C !error: Statement Function is recursive
do j=k+1,N
A(i,j)=A(i,j)-A(k,j)*C !error: Statement Function is recursive
end do
end if
end do
end do
do k=N,1,-1
do i=k-1,1,-1
if(A(k,k)/=0) then
C=A(i,k)/A(k,k)
B(i)=B(i)-B(k)*C !error: Statement Function is recursive
end if
end do
end do
do k=1,N
if(A(k,k)/=0) then
B(k)=B(k)/A(k,k) !error: Statement Function is recursive
end if
end do
end subroutine RowReduction
end module LinearSolution
program TestLAE
use LinearSolution !fatal error: cant open module file LinearSolution.mod for reading
type(LAE)::LAE1
LAE1%N=3
allocate(LAE1%B(1:N))
allocate(LAE1%A(1:N,1:N))
LAE1%B=(/1,1,1/)
LAE1%A=(/2,0,0,0,2,0,0,0,2/)
call LAE1%RowReduction
print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program
通常情况下,
implicit none
是你的朋友
让我们一次处理一个错误:
B(i)=B(i)-B(k)*C !error: Statement Function is recursive
编译器在此上下文中无法识别B
;这里(*)没有声明变量B
,因此它能做的最好的事情是假设它是一个实值,将B定义为I的函数。语句函数是一种节省空间但容易混淆的内联定义函数的方法,但除其他外,它们不能是递归的;在这里,你将用显然失败的B(i)
来定义B(i)
(*)但是!你哭了B
是我的类型中的数组字段LAE
!是的,但我们不在这里的LAE环境中;事实上,在这个函数的上下文中,没有类型为LAE
的变量甚至可以使用的B值。这是因为该过程定义为nopass
;您需要有一个变量,该变量是操作对象的类LAE
,以便我们可以访问这些字段。看起来是这样的:
type LAE
!...
contains
procedure::RowReduction
end type LAE
contains
subroutine RowReduction(self)
class(LAE), intent(InOut) :: self
double precision::C
integer :: i, j, k
do k= 1, self%N
do i= k+1, self%N
if( self%A(k,k) /= 0 ) then
!....
注意,我们必须将self定义为类(LAE)
而不是类型;类是类型的超集,在处理可扩展对象(包括具有(可重新)分配组件的对象)时需要它。还请注意,我们添加了隐式none,它会立即告诉您未定义B
,因此指定了整数索引i、j和k
一旦N
、A
和B
被正确地引用为self
字段,那么程序的大部分其余部分都是正确的。请注意,您必须重塑您的LAE1%A
阵列:
LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))
但在其他方面,情况似乎很好
module LinearSolution
implicit none
type LAE
integer::N
double precision,dimension(:,:),allocatable::A
double precision,dimension( :),allocatable::B
contains
procedure::RowReduction
end type LAE
contains
subroutine RowReduction(self)
class(LAE), intent(InOut) :: self
double precision::C
integer :: i, j, k
do k= 1, self%N
do i= k+1, self%N
if( self%A(k,k) /= 0 ) then
C = self%A(i,k) / self%A(k,k)
self%B(i) = self%B(i)- self%B(k)*C
do j=k+1, self%N
self%A(i,j) = self%A(i,j) - self%A(k,j)*C
end do
end if
end do
end do
do k = self%N,1,-1
do i=k-1,1,-1
if( self%A(k,k)/=0) then
C= self%A(i,k)/ self%A(k,k)
self%B(i)= self%B(i)- self%B(k)*C
end if
end do
end do
do k=1, self%N
if( self%A(k,k)/=0 ) then
self%B(k) = self%B(k) / self%A(k,k)
end if
end do
end subroutine RowReduction
end module LinearSolution
program TestLAE
use LinearSolution
implicit none
integer, parameter :: N = 3
type(LAE)::LAE1
LAE1%N=N
allocate(LAE1%B(1:N))
allocate(LAE1%A(1:N,1:N))
LAE1%B=(/1,1,1/)
LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))
call LAE1%RowReduction
print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program
跑步可以带来:
$ gfortran -o lae lae.f90 -Wall -std=f2003
$ ./lae
0.50000000000000000 0.50000000000000000 0.50000000000000000
很好,尽管我不能同意这是编译器所能做到的最好的。实际错误(未声明的数组)比错误的语句函数明显得多。现代fortran甚至允许语句函数散布在可执行文件中吗?@george:我同意;我能够用gfortran 4.7.2重现错误,但ifort 13为B
提供了一个未声明的数组/函数错误,并假设A
是一个外部函数名。语句函数只允许在规范部分中使用,但它们当然是过时的。