【问题标题】:Fortran Algorithm Help - Getting wrong resultsFortran 算法帮助 - 得到错误的结果
【发布时间】:2012-03-19 01:33:16
【问题描述】:

我目前正在研究一个 fortran 矩阵计算器。我有程序编译,它似乎工作,除了我没有收到正确的结果。当我选择添加功能时,我的程序接受两个矩阵并将它们加在一起。我的结果似乎是错误的。例如,如果我选择两个大小为 2x2 并列出 1 的矩阵作为每个条目,我会收到 3、3、3 的加法结果。我无法弄清楚我在算法中哪里出错了。我还没有检查其他算法,因为我试图一次修复一个算法。下面是我的代码

  *START PROGRAM
  PROGRAM MAIN

  *DECLARATIONS
  INTEGER SELECTION, DONE, VALID, J, I, K, M, N
  INTEGER, DIMENSION(10,10):: SUM, A, B

  *INTITIALIZE
  M = 0
  N = 0
  J = 0
  I = 0
  K = 0
  DONE = 1
  VALID = 1

  *LOOP UNTIL USER CHOOSES TO QUIT

  DO WHILE(DONE .GT. 0)

  *DISPLAY MENU UNTIL VALID ENTRY IS ENTERED

  DO WHILE (VALID .GT. 0)
  *PRINT MENU
  PRINT *,'MATRIX CALCULATOR'
  PRINT *,'PLEASE MAKE A SELECTION'
  PRINT *,'1) MATRIX ADDITION'
  PRINT *,'2) MATRIX SUBTRACTION'
  PRINT *,'3) MATRIX MULTIPLICATION'
  PRINT *,'4) MATRIX TRANSPOSE'
  PRINT *,'5) QUIT PROGRAM'
  READ (*,*) SELECTION

  *VALID ENTRY CHECK
  IF (SELECTION .GT. 5 .OR. SELECTION .LT. 1) THEN
  PRINT *,'PLEASE ENTER A VALID SELECTION'
  ELSE 
  VALID= -1
  END IF

  *END WHEN VALID ENTRY IS ENTERED
  END DO

  *QUIT?
  IF (SELECTION .EQ. 5) THEN
  DONE = -1
  ELSE
  *OTHERWISE CONTINUE
  *GET DIMENTIONS INPUT 
  PRINT *,'PLEASE ENTER THE DIMENTIONS'
  PRINT *,'ENTER IN M:'
  READ (*,*) M
  PRINT *,'ENTER IN N:'
  READ (*,*) N
  *GET IN MATRIX
  PRINT *, 'PLEASE ENTER IN MATRIX A'
  DO J=1, M
  DO I=1, N
  PRINT *, 'ENTER IN VALUE I, I', J, I
  READ(*,*) A(M,N)
  END DO
  END DO

  PRINT *, 'PLEASE ENTER IN MATRIX B'
  DO J=1, M
  DO I=1, N
  PRINT *, 'ENTER IN VALUE I, I', J,I
  READ(*,*) B(M,N)
  END DO
  END DO

  *PERFORM DESIRED CALCULATION
  SELECT CASE(SELECTION)
  *CASE 1
  CASE (1)
   PRINT *,'MATRIX ADDITION'
   DO J=1,M
   DO I=1,N
   SUM(J,I)=A(J,I)+B(J,I)
   END DO   
   END DO

  *PRINT ADDITION RESULT
   PRINT *,'ADDITION RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 2
  CASE (2)
   PRINT *,'MATRIX SUBTRACTION'
   DO J=1,M
   DO I=1,N
   SUM(J,I)=A(J,I)-B(J,I)
   END DO   
   END DO

  *PRINT SUBTRACTION RESULT
   PRINT *,'SUBTRACTION RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 3
  CASE (3)
   PRINT *,'MATRIX MULTIPLICATION'
   DO J=1, M
   DO I=1, N
   DO K=1, N
   SUM(J,I) = SUM(J,I)+A(J,K)*B(I,J)
   END DO
   END DO
   END DO

  *PRINT MULTIPLICATION RESULT
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 4
  CASE (4)
   PRINT *,'MATRIX TRANSPOSE'
   DO J=1, M
   DO I=1, N
   B(I,J) = A(J,I)
   END DO
   END DO
  *PRINT TRANSPOSE RESULT
   PRINT *, 'MATRIX A RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) A(J,I)
   END DO
   END DO
   PRINT *, 'MATRIX B RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) B(J,I)
   END DO
   END DO
  CASE DEFAULT
   PRINT *,'SOMETHING HAS GONE WRONG'
  END SELECT

  *USER SELECTED TO QUIT
  END IF
  END DO
  PRINT *, 'PROGRAM HAS ENDED'
  *END PROGRAM
  STOP
  END

【问题讨论】:

  • 我已经更改了 SUM(I,J) 的写入,并且还增加了 SUM、A、B 的大小。仍然没有运气

标签: algorithm matrix fortran fortran90 matrix-multiplication


【解决方案1】:

避免某些错误的一种方法是使用 Fortran 的数组函数。例如,如果数组 A 和 B 大小相同,您可以使用单个语句求和:

C = A + B

您还可以分别使用内部过程matmultranspose 进行矩阵乘法和转置。

【讨论】:

    【解决方案2】:

    主要问题是在读取矩阵时,您将它们读取到错误的索引。而不是READ(*,*) A(M,N)READ(*,*) B(M,N),你应该有READ(*,*) A(J,I)READ(*,*) B(J,I)

    除此之外,您需要有可分配的数组,而不是将 sum、A 和 B 声明为维度 (1,1)。我还认为将数组命名为 SUM 是不好的做法,因为它与 Fortran 内部函数同名,所以我在这里将其称为 C。像这样声明它们:

    integer, allocatable, dimension(:,:) :: A, B, C
    

    然后在您从用户那里读取尺寸后,执行以下操作:

    allocate(A(m, n))
    

    通过这些更改,当将 (1,1;1,1) 添加到 (1,1;1,1) 时,我得到 (2,2;2,2)。

    一般来说,我还建议正确缩进循环而不是全部使用大写字母,这会使代码更难阅读。

    【讨论】:

      【解决方案3】:

      这就是问题所在:

        *PRINT ADDITION RESULT
         PRINT *,'ADDITION RESULT'
         DO J=1, M
         DO I=1, N
         WRITE (*,*) SUM(N,M)
         END DO
         END DO
      

      你应该有WRITE (*,*) SUM(J,I)

      【讨论】:

      • 谢谢。我纠正了这个问题,但我仍然得到不正确的结果。如果我添加 1,1;1,1 + 1,1;1,1 我收到的答案是 1;2;2;3
      • 您的 READ 行也遇到了完全相同的问题,即:READ(*,*) A(M,N) -> READ(*,*) A(J,I)。与 B 中的阅读类似。
      【解决方案4】:

      您将 SUMAB 声明为 1x1 数组,然后在程序中您在声明的边界之外引用它们。任何事情都可能发生。

      【讨论】:

        【解决方案5】:

        如果您选择适当的运行时测试,编译器会自动捕获其他答案中提到的一些错误(例如,越界下标)。选择编译器的广泛警告和错误检查选项将帮助您更快地发现错误。您使用的是哪个编译器?

        【讨论】:

        • 我目前正在使用 VAX 编译器
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-09
        • 1970-01-01
        • 2014-11-11
        • 1970-01-01
        • 1970-01-01
        • 2020-03-01
        • 2023-02-11
        相关资源
        最近更新 更多