3

这是试图解决一个 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
4

1 回答 1

5

通常情况下,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 定义为 ofclass(LAE)而不是 type;class 是类型的超集,在处理可扩展对象时需要它,这些可扩展对象包括具有(重新)可分配组件的对象。还要注意,我们添加了隐式 none,它会立即告诉您B没有定义,因此指定了整数索引 i、j 和 k。

一旦NAB被正确引用为 的字段self,那么程序的其余大部分都是正确的。请注意,您必须对reshape数组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     
于 2012-12-29T04:12:24.447 回答