Fortran学习19:数值计算方法2

老感觉昨天自己最后写的那个python牛顿法求解,老觉得不太对,,其实后面我想学完Fortran之后,再跟着matlab书把数据处理再学一下,因为Fortran那本书讲的东西实在是太少了。,而且听师兄说,我们不用Fortran绘图,后面还是matlab和python来绘图。

今天先不说了,直接开始矩阵运算,其实矩阵的加减法没啥好说的,就是相同位置进行加减运算就行了,主要是乘法,Fortran库里有一个matmul()函数来计算,但是今天还是先自己敲吧。

program main
    implicit none
    integer::a(3,3)
    integer::b(3,3)
    integer::c(3,3)
    integer i,j,k
    data a / 1,2,3,4,5,6,7,8,9 /
    data b /10,11,12,13,14,15,16,17,18/
    ! 加法
    !可以直接使用c=a+b,下面是为了展示运算过程
    do i=1,3
        do j=1,3
            c(i,j)=a(i,j)+b(i,j)
        end do
    end do
    ! 减法
    !可以直接使用c=a-b,下面是为了展示运算过程
    do i=1,3
        do j=1,3
            c(i,j)=a(i,j)-b(i,j)
        end do
    end do
    ! 乘法
    do i=1,3
        do j=1,3
            c(i,j)=0
            do k=1,3
                c(i,j)=c(i,j)+a(i,k)*b(k,j)
            end do 
        end do
    end do
    ! 再试试Fortran自带的函数matmul
    c=MATMUL(a,b)
    write(*,"(I5,I5,I5/I5,I5,I5/I5,I5,I5)")c
    stop "over"
end program 

放心,没问题的,ctrl+c,ctrl+v之后完全可以运行。

其实也可以在主程序外面把这几个运算方法写成function或者subroutine,我觉得都还行,就是个传参嘛。反正我是没有用书上的代码,习惯了,不喜欢整个程序纯粹用大写字母。

1、三角矩阵:上三角和下三角,上三角对角线以下的数全部是0,相应的,下三角对角线以上的全部是零:

跟着书上的代码敲一遍吧,我线代的储备主要还是考研时候听网课攒的点底子(大二学线代的时候才考了85+,有点低)

module LinearAlgebra
    implicit none
    contains
        subroutine output(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i
            CHARACTER(len=20)::for='(??(1x,f6.3))'
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            WRITE(for(2:3),'(I2)')N
            do i=1,N
                write(*,Fmt=for)matrix(i,:)
            end do
            return 
        end subroutine 
        ! 求解上三角矩阵:
        subroutine upper(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i,j
            real::e
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            do I=1,n-1
                do j=i+1,m
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,i:m)=matrix(j,i:m)-matrix(i,i:m)*e
                end do
            end do
            return 
        end subroutine
        ! 求解下三角矩阵:
        subroutine lower(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i,j
            real::e
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            do I=n,2,-1
                do j=i-1,1,-1
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,1:i)=matrix(j,1:i)-matrix(i,1:i)*e
                end do
            end do
            return 
        end subroutine
end module
program main
    use LinearAlgebra
    implicit none
    INTEGER,PARAMETER::n=3
    real::a(n,n),b(n,n)
    data a / 1,2,1,3,2,3,2,3,4 /
    write(*,*)"Matrix A:"
    CALL output(a)
    b=a
    write(*,*)"Upper:"
    CALL upper(b)
    CALL output(b)
    b=a
    write(*,*)"lower:"
    CALL upper(b)
    CALL output(b)
    stop "over"
end program 
    

输出:

 学习上下三角矩阵的目的就是,可以应用在determinant、gauss-jordan发求解联立式、求逆矩阵等。

下午如果有时间的话我就学着写写determinant、gauss-jordan和求逆矩阵如果没时间的话那就算了。

哈哈,下午有时间!

Determinant:就是把矩阵转化成上三角矩阵,然后求行列式值,把这段代码加到module里面就可以调用。

        real function Determinant(matrix)
            real::matrix(:,:)
            real,ALLOCATABLE::ma(:,:)
            integer::i,n
            n=size(matrix, dim=1)
            ALLOCATE(ma(n,n))
            ma=matrix
            CALL upper(ma)
            Determinant=1.0
            do i=1,n
                Determinant=Determinant*ma(i,i)
            end do
        end function 

 Gauss-Jordan法求联立方程式:

        subroutine Gauss_Jordan(a,s,ans)
            real::a(:,:)
            real::s(:)
            real::ans(:)
            real,ALLOCATABLE::b(:,:)
            integer :: i
            integer :: n 
            n=size(a, dim=1)
            ALLOCATE(b(n,n))
            b=a
            ans=s
            call upper1(b,ans,n)
            call lower1(b,ans,n)
            do i=1,n
                ans(i)=ans(i)/b(i,i)
            end do
            RETURN
        end subroutine
        subroutine output1(m,s)
            implicit none
            real::m(:,:),s(:)
            integer i,j,n
            n=size(m, dim=1)
            do i=1,n
                write(*,"(1x,f5.2,a1)",advance="no")m(i,1),'a'
                do j=2,n
                    if(m(i,j)<0)then
                        write(*,"('-',f5.2,a1)",advance="no")-m(i,j),char(64+j)
                    else
                        write(*,"('+',f5.2,a1)",advance="no")m(i,j),char(64+j)
                    end if
                end do 
            end do 
        end subroutine
        subroutine upper1(matrix,s,n)
            implicit none
            integer::n
            real::matrix(n,n)
            real::s(n)
            integer::i,j
            real::e
            do I=1,n-1
                do j=i+1,n
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,i:n)=matrix(j,i:n)-matrix(i,i:n)*e
                    s(j)=s(j)-s(i)*e
                end do
            end do
            return 
        end subroutine
        ! 求解下三角矩阵:
        subroutine lower1(matrix,s,n)
            implicit none
            integer::n
            real::matrix(:,:)
            real::s(n)
            integer::i,j
            real::e
            do I=n,2,-1
                do j=i-1,1,-1
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,1:n)=matrix(j,1:n)-matrix(i,1:n)*e
                    s(j)=s(j)-s(i)*e
                end do
                write(*,"('=',f8.4)")s(i)
            end do
            return 
        end subroutine

上面两段代码加到module里面就好,直接运行。

 Gauss_Jordan是用来求解方程组的。

逆矩阵,实际上书上介绍的方法就是在要求逆矩阵的矩阵后面加上一个单位矩阵,然后把前者处理成单位矩阵,前者每一次处理的时候,后者要跟着进行相同的操作,之后得到的就是逆矩阵。

        subroutine inverse(a,b)
            implicit none
            real::a(:,:),b(:,:)
            real,ALLOCATABLE::c(:,:)
            integer i,j,n
            n=size(a, dim=1)
            allocate(c(n,n))
            forall(i=1:n,j=1:n,i==j)b(i,j)=1.0
            forall(i=1:n,j=1:n,i/=j)b(i,j)=0.0
            c=a
            call upper1(c,b,n)
            call lower1(c,b,n)
            forall(i=1:n)b(i,:)=b(i,:)/b(i,i)
            return
        end subroutine

 

这下求出来的就是matrix的逆矩阵啦,同样的,上面的subroutine直接加到module里面就可以调用它了。

至于使用嘛,就看你到底要处理什么问题了,比如说求解下面的对角矩阵啊,解方程组之类的,都可以,具体情况具体看待。

\begin{bmatrix} 2 3 0 0 0 0 0\\ 1 2 3 0 0 0 0\\ 0 1 2 3 0 0 0 \\ 0 0 1 2 3 0 0 \\ 0 0 0 1 2 3 0\\ 0 0 0 0 1 2 3\\ 0 0 0 0 0 1 2 \end{bmatrix}

ok,把今天的完整代码附上:

module LinearAlgebra
    implicit none
    contains
        !  Determinant矩阵
        real function Determinant(matrix)
            real::matrix(:,:)
            real,ALLOCATABLE::ma(:,:)
            integer::i,n
            n=size(matrix, dim=1)
            ALLOCATE(ma(n,n))
            ma=matrix
            CALL upper(ma)
            Determinant=1.0
            do i=1,n
                Determinant=Determinant*ma(i,i)
            end do
        end function 
        
        ! 求解联立方程组
        subroutine Gauss_Jordan(a,s,ans)
            real::a(:,:)
            real::s(:)
            real::ans(:)
            real,ALLOCATABLE::b(:,:)
            integer :: i
            integer :: n 
            n=size(a, dim=1)
            ALLOCATE(b(n,n))
            b=a
            ans=s
            call upper1(b,ans,n)
            call lower1(b,ans,n)
            do i=1,n
                ans(i)=ans(i)/b(i,i)
            end do
            RETURN
        end subroutine

        ! 逆矩阵求解
        subroutine inverse(a,b)
            implicit none
            real::a(:,:),b(:,:)
            real,ALLOCATABLE::c(:,:)
            integer i,j,n
            n=size(a, dim=1)
            allocate(c(n,n))
            forall(i=1:n,j=1:n,i==j)b(i,j)=1.0
            forall(i=1:n,j=1:n,i/=j)b(i,j)=0.0
            c=a
            call upper1(c,b,n)
            call lower1(c,b,n)
            forall(i=1:n)b(i,:)=b(i,:)/b(i,i)
            return
        end subroutine

        ! 输出
        subroutine output(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i
            CHARACTER(len=20)::for='(??(1x,f6.3))'
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            WRITE(for(2:3),'(I2)')N
            do i=1,N
                write(*,Fmt=for)matrix(i,:)
            end do
            return 
        end subroutine 

        ! 求解上三角矩阵:
        subroutine upper(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i,j
            real::e
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            do I=1,n-1
                do j=i+1,m
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,i:m)=matrix(j,i:m)-matrix(i,i:m)*e
                end do
            end do
            return 
        end subroutine
        
        ! 求解下三角矩阵:
        subroutine lower(matrix)
            implicit none
            integer::m,n
            real::matrix(:,:)
            integer::i,j
            real::e
            m=size(matrix, dim=1)
            n=size(matrix, dim=2)
            do I=n,2,-1
                do j=i-1,1,-1
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,1:i)=matrix(j,1:i)-matrix(i,1:i)*e
                end do
            end do
            return 
        end subroutine

        ! 输出1:供gauss——jordan使用
        subroutine output1(m,s)
            implicit none
            real::m(:,:),s(:)
            integer i,j,n
            n=size(m, dim=1)
            do i=1,n
                write(*,"(1x,f5.2,a1)",advance="no")m(i,1),'a'
                do j=2,n
                    if(m(i,j)<0)then
                        write(*,"('-',f5.2,a1)",advance="no")-m(i,j),char(64+j)
                    else
                        write(*,"('+',f5.2,a1)",advance="no")m(i,j),char(64+j)
                    end if
                end do 
            end do 
        end subroutine

        ! 求解上三角矩阵1
        subroutine upper1(matrix,s,n)
            implicit none
            integer::n
            real::matrix(n,n)
            real::s(n)
            integer::i,j
            real::e
            do I=1,n-1
                do j=i+1,n
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,i:n)=matrix(j,i:n)-matrix(i,i:n)*e
                    s(j)=s(j)-s(i)*e
                end do
            end do
            return 
        end subroutine
        
        ! 求解下三角矩阵1:
        subroutine lower1(matrix,s,n)
            implicit none
            integer::n
            real::matrix(:,:)
            real::s(n)
            integer::i,j
            real::e
            do I=n,2,-1
                do j=i-1,1,-1
                    e=matrix(j,i)/matrix(i,i)
                    matrix(j,1:n)=matrix(j,1:n)-matrix(i,1:n)*e
                    s(j)=s(j)-s(i)*e
                end do
                write(*,"('=',f8.4)")s(i)
            end do
            return 
        end subroutine
end module
program main
    use LinearAlgebra
    implicit none
    INTEGER,PARAMETER::n=3
    real::a(n,n),b(n,n)
    real::a1(n,n),s(n),ans(n)
    integer i
    data a / 1,2,1,3,2,3,2,3,4 /
    data a1 / 1,2,3,4,5,6,7,8,8 /
    data s / 12,15,17 /

    write(*,*)"equation"
    CALl output1(a,s)
    call Gauss_Jordan(a,s,ans)
    write(*,*)"ans="
    
    do i=1,n
        write(*,"(1x,a1,'=',f8.4)")char(64+i),ans(i)
    end do
    
    write(*,*)"matrix:"
    call output(a)
    call inverse(a,b)
    
    write(*,*)"inverse"
    call output(b)
    
    write(*,*)"Matrix A:"
    CALL output(a)

    b=a
    write(*,*)"Upper:"
    CALL upper(b)
    CALL output(b)
    
    b=a
    write(*,*)"lower:"
    CALL upper(b)
    CALL output(b)
    write(*,"('det(A)=',F6.2)")Determinant(a)
    stop "over"
end program 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值