我过去几天才学习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 - BPRINT *, "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 - BPRINT *, "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
答案 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)
在主程序中z
为real z(2,2)
,而不是您示例中的标量blah
,并且是您的结果。
来到你的子程序,确实存在问题:real subroutine matmult(x,y,z)
不需要real
。然后使用call matmult(mat0, mat0, mat0)
调用此处,并打算使用结果更新mat0
,这就是要求出现别名问题。 call matmult(x,y,z)
将“存储结果”存储在子程序计算所在的位置。使用Ilmirus给出的intent
可以很好地指导程序员所需的行为。
最后,如果您只想获得将A
和B
相乘作为矩阵并存储在C
中的结果:使用C = matmul(A,B)
与F77之后的结果编译器。
但是,在Fortran 77中,没有返回数组结果,所以子程序方法是最合适的。为了回应你的编辑:
REAL MATMULT(2,2)
声明matmult
数组,而不是函数,因此对matmult(X,Y)
的引用会导致错误。