nor*_*fly 3 recursion fortran module subroutine fortran90
这是试图解决3*3的线性方程并打印出结果,但它在注释行中出现问题:
我在程序之外定义了LinearSolution模块,我应该在里面定义它吗?有什么不同?
为什么它说这个语句是递归的,你知道,当我使用这些语句作为普通的子程序而不是模块子程序时,它们被证实是好的.
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
Run Code Online (Sandbox Code Playgroud)
像往常一样,implicit none是你的朋友.
让我们一次一个地抓错误:
B(i)=B(i)-B(k)*C !error: Statement Function is recursive
Run Code Online (Sandbox Code Playgroud)
编译器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
!....
Run Code Online (Sandbox Code Playgroud)
请注意,我们必须将self定义为class(LAE)而不是类型; class是类型的超集,在处理包含具有(重新)可分配组件的对象的可扩展对象时是必需的.另请注意,我们添加了隐式none,它会立即告诉您B未定义的内容,因此指定了整数索引i,j和k.
一旦N,A并且B被正确引用为字段self,那么程序的其余部分都是正确的.请注意,您必须使用reshape您的LAE1%A数组:
LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))
Run Code Online (Sandbox Code Playgroud)
但其他情况似乎很好.
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
Run Code Online (Sandbox Code Playgroud)
跑步给出:
$ gfortran -o lae lae.f90 -Wall -std=f2003
$ ./lae
0.50000000000000000 0.50000000000000000 0.50000000000000000
Run Code Online (Sandbox Code Playgroud)