0

我正在开发一个有趣的小矩阵计算器程序来完善我的 Fortran,但我遇到了一些问题。除了乘法和转置之外,一切都运行良好。当我乘以时,我得到的答案是完全错误的,我不确定为什么会这样。例如:如果我乘

| 1 2 3 |   | 1 2 |
| 4 5 6 | * | 3 4 |
            | 5 6 |

I get | 26  32 |
      | 10  16 |
but wolframalpha says I should be getting 

| 22  28 |
| 49  64 |

另外,至于转置,如果我尝试转置

| 1 2 3 |
| 4 5 6 |
| 7 8 9 |,
I get 
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |

而不是它应该是什么。

下面是我的整个程序,因此您可以自己编译它并查看问题所在。我怀疑问题在于输出、乘法和转置子例程。

        PROGRAM G6P5
        integer :: r1,r2,c1,c2,i,j,k,s
        real :: input
        real, dimension (11,11) :: mat1, mat2, rmat
        write (*,*) 'Please make a selection:'
        write (*,*) 'Enter 1 to add matrices'
        write (*,*) 'Enter 2 to subtract matrices'
        write (*,*) 'Enter 3 to multiply matrices'
        write (*,*) 'Enter 4 to transpose a matrix'
        write (*,*) 'Enter 5 to quit'
        read *, s
        select case (s)
            case (1)
                print *, 'Enter # of rows & columns (1-10) (ex. 3 3 = 3x3)'
                read *, r1,c1
              print *, 'Matrix 1:'
                call fillmatrix(r1,c1,mat1)
                r2 = r1
                c2 = c1
                print *, 'Matrix 2:'
                call fillmatrix(r2,c2,mat2)
                call output(r1,c1,mat1,'Matrix 1: ')
                call output(r2,c2,mat2,'Matrix 2: ')
                rmat = mat1+mat2
                call output(r1,c1,rmat,'Sum:      ')
            case (2)
                print *, 'Enter # of rows & columns (1-10) (ex. 3 3 = 3x3)'
                read *, r1,c1
              print *, 'Matrix 1:'
                call fillmatrix(r1,c1,mat1)
                r2 = r1
                c2 = c1
                print *, 'Matrix 2:'
                call fillmatrix(r2,c2,mat2)
                rmat = mat1-mat2
                call output(r1,c1,mat1,'Matrix 1: ')
                call output(r2,c2,mat2,'Matrix 2: ')
                call output(r1,c1,rmat,'Sum:      ')
            case (3)
                print *, 'Enter # of rows & columns for matrix 1'
                print *, '(1 through 10, ex: 3 3 = 3x3)'
                read *, r1,c1
              print *, 'Matrix 1:'
                call fillmatrix(r1,c1,mat1)
                print *, 'Enter # of rows & columns for matrix 2'
                print *, '(1 through 10, ex: 3 3 = 3x3)'
                read *, r2,c2
              print *, 'Matrix 2:'
                call fillmatrix(r2,c2,mat2)
                if (c1.eq.r2) then
                    call multiply(mat1,mat2,rmat,r1,r2,c1,c2)
                    call output(r1,c1,mat1,'Matrix 1: ')
                    call output(r2,c2,mat2,'Matrix 2: ')
                    call output(r1,c2,rmat,'Product:  ')
                end if
            case (4)
                print *, 'Enter # of rows & columns for matrix 1'
                print *, '(1 through 10, ex: 3 3 = 3x3)'
                read *, r1,c1
              print *, 'Matrix 1:'
                call fillmatrix(r1,c1,mat1)
                call transpose(mat1,rmat,r1,c1)
                call output(r1,c1,rmat,'Transpose:')
            case (5)
                print *,'5'
            case default
                print *,'default'
        end select
        !       call fillmatrix(rows,columns,mat1)
        !       write (*,*) matrix1
        END PROGRAM




        subroutine fillmatrix(r,c,matrix)
            integer, intent(in) :: r
            integer, intent(in):: c
            real, intent(out), dimension(r,c) :: matrix

            integer i,j

            do i=1,r
                do j = 1,c
                    write (*,'(A,I2,A,I2,A)') 'Enter value (',i,',',j,').'
                    read*, matrix(i,j)
                enddo
            enddo
        end subroutine


        subroutine multiply(m1,m2,res,row1,row2,col1,col2)
            integer, intent(in) :: row1,row2,col1,col2
            real, intent(in), dimension(row1,col1) :: m1
            real, intent(in), dimension(row2,col2) :: m2
            real, intent(out), dimension(row1,col2) :: res

            integer :: i,j,k

            do i = 1, col2
            do j = 1, col1
                res(j, i) = 0
          enddo
          do j = 1, col1
              do k = 1, row1
                  res(k, i) = res(k, i) + m1(k, j)*m2(j, i)
              enddo
          enddo
       enddo


        end subroutine

        subroutine transpose(m1,res,row,col)
            integer, intent(in) :: row,col
            real, intent(in), dimension(row,col) :: m1
            real, intent(out), dimension(row,col) :: res

            integer :: i,j,k
            do i = 1,col
                do j = 1,row
                    res(i,j) = m1(j,i)
                enddo
            enddo
        end subroutine



        subroutine output(r,c,matrix,name)
            integer, intent(in) :: r
            integer, intent(in):: c
            character(len=10) :: name
            real, intent(out), dimension(3,3) :: matrix


            integer i,j

            print *,name
            do i = 1, r
                    write(*,"(100F6.1)") ( matrix(i,j), j=1,c )
            enddo
        end subroutine
4

2 回答 2

1

几点评论:

  • 最好使用CONTAINSbeforeEND PROGRAM并将所有子程序放在主程序的包含和结尾之间,而不是将所有子程序都放在那里
  • 在一些地方,您指定矩阵INTENT(OUT)的显式维度为(3,3); 它应该是INTENT(IN)或者INTENT(INOUT)这些特定的地方,并且应该有一个明确的维度(r,c)
  • 你可以指定CHARACTER(LEN=*)而不用担心你的字符串有多长

也就是说,我没有发现转置有什么问题,我得到了

1 2 3        1 4 7
4 5 6   -->  2 5 8
7 8 9        3 6 9

正如预期的那样。但是,如果您查看矩阵乘法的输出,我尝试输入

1 2 3
4 5 6

作为矩阵 1 并收到

1 0 5
4 2 0

作为输出,而矩阵 2 符合预期。

错误是要点#2:您的尺寸在您的fillmatrix日常工作中被搞砸了。更改这些确实可以修复您的矩阵,但我认为您的multiply例程有问题,因为它仍然给出错误的答案。

于 2013-10-10T00:53:09.617 回答
0

最好使用可分配的然后使用固定尺寸。

将您的子例程放入模块中将允许对参数进行大量一致性检查。

矩阵乘法:

subroutine multiply(m1,m2,res,row1,row2,col1,col2)
  integer, intent(in) :: row1,row2,col1,col2
  integer, intent(in), dimension(row1,col1) :: m1
  integer, intent(in), dimension(row2,col2) :: m2
  integer, intent(out), dimension(row1,col2) :: res

  integer :: i,j,k

  res = 0
  do i = 1, row1
     do j = 1, col2
        do k = 1, col1   ! col1 must equal row2
           res(i, j) = res(i, j) + m1(i, k)*m2(k, j)
        enddo   ! k
      enddo  ! j
  enddo  ! i


end subroutine

编辑:试试这个:

module MySubs
contains

subroutine fillmatrix(r,c,matrix)
  integer, intent(in) :: r
  integer, intent(in):: c
  integer, intent(out), dimension(r,c) :: matrix

  integer i,j

  do i=1,r
      do j = 1,c
          write (*,'(A,I2,A,I2,A)') 'Enter value (',i,',',j,').'
          read*, matrix(i,j)
      enddo
  enddo
end subroutine


subroutine multiply(m1,m2,res,row1,row2,col1,col2)
  integer, intent(in) :: row1,row2,col1,col2
  integer, intent(in), dimension(row1,col1) :: m1
  integer, intent(in), dimension(row2,col2) :: m2
  integer, intent(out), dimension(row1,col2) :: res

  integer :: i,j,k

  res = 0
  do i = 1, row1
     do j = 1, col2
        do k = 1, col1   ! col1 must equal row2
           res(i, j) = res(i, j) + m1(i, k)*m2(k, j)
        enddo   ! i
      enddo  ! j
  enddo  ! k


end subroutine

subroutine transpose(m1,res,row,col)
  integer, intent(in) :: row,col
  integer, intent(in), dimension(row,col) :: m1
  integer, intent(out), dimension(col,row) :: res

  integer :: i,j,k
  do i = 1,col
      do j = 1,row
          res(i,j) = m1(j,i)
      enddo
  enddo
end subroutine



subroutine output(r,c,matrix,name)
  integer, intent(in) :: r
  integer, intent(in):: c
  character(len=10) :: name
  integer, intent(out), dimension(:,:) :: matrix


  integer i,j

  print *,name
  do i = 1, r
          write(*,"(100I6)") ( matrix(i,j), j=1,c )
  enddo
end subroutine

end module MySubs

PROGRAM G6P5
use MySubs
integer :: r1,r2,c1,c2,i,j,k,s,input
integer, dimension (:,:), allocatable :: mat1, mat2, rmat
write (*,*) 'Please make a selection:'
write (*,*) 'Enter 1 to add matrices'
write (*,*) 'Enter 2 to subtract matrices'
write (*,*) 'Enter 3 to multiply matrices'
write (*,*) 'Enter 4 to transpose a matrix'
write (*,*) 'Enter 5 to quit'
read *, s
select case (s)
  case (1)
      print *, 'Enter # of rows & columns (1-10) (ex. 3 3 = 3x3)'
      read *, r1,c1
      allocate (mat1 (r1,c1))
    print *, 'Matrix 1:'
      call fillmatrix(r1,c1,mat1)
      r2 = r1
      c2 = c1
      allocate (mat2 (r2,c2))
      print *, 'Matrix 2:'
      call fillmatrix(r2,c2,mat2)
      call output(r1,c1,mat1,'Matrix 1: ')
      call output(r2,c2,mat2,'Matrix 2: ')
      allocate (rmat (r1,c1))
      rmat = mat1+mat2
      call output(r1,c1,rmat,'Sum:      ')
  case (2)
      print *, 'Enter # of rows & columns (1-10) (ex. 3 3 = 3x3)'
      read *, r1,c1
      allocate (mat1 (r1,c1))
    print *, 'Matrix 1:'
      call fillmatrix(r1,c1,mat1)
      r2 = r1
      c2 = c1
      allocate (mat2 (r2,c2))
      print *, 'Matrix 2:'
      call fillmatrix(r2,c2,mat2)
      allocate (rmat (r1,c1))
      rmat = mat1-mat2
      call output(r1,c1,mat1,'Matrix 1: ')
      call output(r2,c2,mat2,'Matrix 2: ')
      call output(r1,c1,rmat,'Sum:      ')
  case (3)
      print *, 'Enter # of rows & columns for matrix 1'
      print *, '(1 through 10, ex: 3 3 = 3x3)'
      read *, r1,c1
      allocate (mat1 (r1,c1))
    print *, 'Matrix 1:'
      call fillmatrix(r1,c1,mat1)
      print *, 'Enter # of rows & columns for matrix 2'
      print *, '(1 through 10, ex: 3 3 = 3x3)'
      read *, r2,c2
      allocate (mat2 (r2,c2))
    print *, 'Matrix 2:'
      call fillmatrix(r2,c2,mat2)
      if (c1.eq.r2) then
          allocate (rmat (r1,c2))
          call multiply(mat1,mat2,rmat,r1,r2,c1,c2)
          call output(r1,c1,mat1,'Matrix 1: ')
          call output(r2,c2,mat2,'Matrix 2: ')
          call output(r1,c2,rmat,'Product:  ')
      else
         write (*, *) "incompatible dimensions"
      end if
  case (4)
      print *, 'Enter # of rows & columns for matrix 1'
      print *, '(1 through 10, ex: 3 3 = 3x3)'
      read *, r1,c1
      allocate (mat1 (r1,c1))
    print *, 'Matrix 1:'
      allocate (rmat (c1,r1))
      call fillmatrix(r1,c1,mat1)
      call transpose(mat1,rmat,r1,c1)
      call output(r1,c1,rmat,'Transpose:')
  case (5)
      print *,'5'
  case default
      print *,'default'
end select
!       call fillmatrix(rows,columns,mat1)
!       write (*,*) matrix1
END PROGRAM
于 2013-10-10T01:25:53.653 回答