Fortran 77:如何使用函数或子程序的数组输出

时间:2014-02-10 00:04:28

标签: arrays matrix fortran fortran77

我过去几天才学习Fortran 77(以及它的语法),并尝试在整个网站和教科书中找到答案并且仍然感到困惑,所以我很感激任何帮助。如果这篇文章的格式关闭,我很抱歉;这是我的第一篇文章,我时间紧张。

我正在创建一个乘法矩阵的程序。我想创建一个子程序或一个函数,它将两个矩阵作为输入(两个2x2数组),并返回乘法矩阵(一个2x2数组)。我无法弄清楚如何获得子程序或函数来返回固定大小的数组,或者如何在返回数组后使用该数组。

我尝试使用一个自己编译的函数。但是当我尝试从我的主程序调用该函数时,我无法单独调用它:

 MATMULT(MAT0, MAT0, MAT0)                                        
 1
 Error: Unclassifiable statement at (1) 

或将其分配给另一个变量(我尝试了不同的REAL和数组):

  BLAH = MATMULT(MAT0, MAT0, MAT0)                                 
                1
  Error: Return type mismatch of function 'matmult' at (1) (INTEGER(4)/REAL(4))
  MATRIX1.f:26.22:

  BLAH = MATMULT(MAT0, MAT0, MAT0)                                 
                 1
  Warning: Type mismatch in argument 'x' at (1); passed INTEGER(4) to REAL(4)

  BLAH = MATMULT(MAT0, MAT0, MAT0)                                 
                 1
  Warning: Rank mismatch in argument 'x' at (1) (scalar and rank-2)

由于数组是通过引用传递的,我真的不确定函数返回的是什么,所以我如何使用输出矩阵,如果那确实是函数的输出?

我也试过使用子程序,但是(除了还不知道它返回的是什么或在哪里)然后我得到一个“两个主程序”错误 - 所以编译器没有区分主程序和子程序。这可能是我在子程序上的语法问题?我尝试了一些不同的东西,但这是我最近的代码迭代(我只是想让数组传递工作,所以这里还没有实际的矩阵乘法):

  PROGRAM MATRIX1

  INTEGER N 
  REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
  REAL BLAH


  PRINT *, " ENTER THE VALUE OF A: "
  READ *, A
  PRINT *, " ENTER THE VALUE OF B: "
  READ *, B
  PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
  READ *, N
     

C创建初始矩阵
        MAT0(1,1)= 1.0 - A.         MAT0(1,2)= A.         MAT0(2,1)= B.         MAT0(2,2)= 1.0 - B

  PRINT *, "M = ", MAT0

  CALL MATMULT(MAT0, MAT0, MAT0)
  PRINT *, "FINAL "


  STOP
  END PROGRAM

  REAL SUBBROUTINE MATMULT(X, Y, Z)

      END SUBROUTINE

或(使用函数编辑以添加一些建议的更改):

  PROGRAM MATRIX1

  INTEGER N 
  REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
  REAL MATMULT(2,2)


  PRINT *, " ENTER THE VALUE OF A: "
  READ *, A
  PRINT *, " ENTER THE VALUE OF B: "
  READ *, B
  PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
  READ *, N
     

C创建初始矩阵
        MAT0(1,1)= 1.0 - A.         MAT0(1,2)= A.         MAT0(2,1)= B.         MAT0(2,2)= 1.0 - B

  PRINT *, "M = ", MAT0

  Z = MATMULT(X, Y)


  STOP
  END PROGRAM

  FUNCTION MATMULT(X, Y)
      REAL X(2,2), Y(2,2), Z(2,2), MATMULT(2,2)
      RETURN
      END

我仍然遇到错误:

  Z = MATMULT(X, Y)                                                
              1
  Warning: Legacy Extension: REAL array index at (1)
  MATRIX1.f:28.19:

  Z = MATMULT(X, Y)                                                
              1
  Error: Array index at (1) is an array of rank 2

3 个答案:

答案 0 :(得分:1)

在这个时代,没有理由使用FORTRAN 77. Fortran 90/95/2003更易于使用,功能更强大,更好地帮助程序员找到错误。 gfortran是一个优秀的开源编译器。

这是类似程序/函数的Fortran 95中的一个示例:实现矢量交叉产品的函数。该示例显示了同一文件中的函数和程序(还有其他方法),函数接收两个向量并返回一个向量。示例:Computing the cross product of two vectors in Fortran 90

答案 1 :(得分:0)

有两种方法可以做到这一点:

1)子程序。像你一样声明一个子程序。但是,请指定输入和输出参数:

REAL, INTENT(IN) :: X(2,2), Y(2,2)
REAL, INTENT(OUT) :: Z(2,2)

并使用call关键字CALL MATMULT

调用子例程

2)功能。同时指定输入参数,但现在返回函数的值:

! Insert calculation
MALMULT = ... 

不要忘记以正确的方式声明:FUNCTION MATMULT(x,Y)

称之为:Z = MATMULT(X,Y)

答案 2 :(得分:0)

你在问题​​中提到了几个问题。当然,使用最新的Fortran方言可以增强你的工作,正如M. S. B.和Ilmirus的答案所给出的那样。而且你真的应该使用implicit none(即使对于Fortran 77,很多编译器也支持 - 以及小写 - 作为扩展)。

来到概念部分,我必须说你需要继续学习。但是,如果您想要一个返回矩阵产品的函数,那么您将拥有类似

的函数
function matmult(x, y)
  real x(2,2), z(2,2), matmult(2,2)
  ... calculation of matmult
end function matmult

其次是

z = matmult(x,y)

在主程序中zreal z(2,2),而不是您示例中的标量blah,并且是您的结果。

来到你的子程序,确实存在问题:real subroutine matmult(x,y,z)不需要real。然后使用call matmult(mat0, mat0, mat0)调用此处,并打算使用结果更新mat0,这就是要求出现别名问题。 call matmult(x,y,z)将“存储结果”存储在子程序计算所在的位置。使用Ilmirus给出的intent可以很好地指导程序员所需的行为。

最后,如果您只想获得将AB相乘作为矩阵并存储在C中的结果:使用C = matmul(A,B)与F77之后的结果编译器。

但是,在Fortran 77中,没有返回数组结果,所以子程序方法是最合适的。为了回应你的编辑:

  REAL MATMULT(2,2)

声明matmult数组,而不是函数,因此对matmult(X,Y)的引用会导致错误。