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

いくつかのコメント:

  • CONTAINSすべてのサブルーチンをそこに置くよりも、メインプログラムの前に使用END 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は予想通りでしたが、出力として。

fillmatrixそして、バグは箇条書き 2 です。あなたの寸法は、あなたのルーチンで台無しにされています。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 に答える