2014-02-10 7 views
0

나는 Fortran 77 (및 구문)을 지난 며칠 동안 배웠으며 사이트 및 교과서에서 이미 답변을 찾지 만 여전히 혼란스러워 보입니다. 나는 어떤 도움을 주셔서 감사합니다. 이 게시물의 서식이 꺼져 있으면 죄송합니다. 이것은 내 첫 번째 게시물이며, 나는 시간을 위해 crunched 해요.Fortran 77 : 함수 또는 서브 루틴에서 배열 출력을 사용하는 방법

매트릭스를 곱하는 프로그램을 만들고 있습니다. 두 개의 행렬을 입력 (두 개의 2x2 배열)으로 사용하고 곱해진 행렬 (하나의 2x2 배열)을 반환하는 서브 루틴이나 함수를 만들고 싶습니다. 서브 루틴이나 함수를 사용하여 고정 된 크기의 배열을 반환하는 방법이나 반환 된 배열을 사용하는 방법을 알아낼 수 없습니다.

나는 자체적으로 컴파일 된 함수를 사용해 보았습니다. 내 메인 프로그램에서 함수를 호출 시도 때, 나는 스스로를 호출 할 수 있습니다 :

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) 
:

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

을하거나 다른 변수에 할당 (I 다른 REAL이와 배열을 시도)

배열을 참조로 전달했기 때문에 함수가 무엇을 반환하는지 잘 모르겠습니다. 실제로 함수의 출력 인 경우 출력 매트릭스를 어떻게 사용할 수 있습니까?

서브 루틴을 사용해 보았지만 (무엇이 반환되는지 또는 어디에 있는지도 알지 못함) "두 개의 주요 프로그램"오류가 발생합니다. 따라서 컴파일러는 주 프로그램과 서브 루틴을 구별하지 않습니다 . 서브 루틴에 대한 내 구문에 문제가있을 수 있습니까? 나는 몇 가지 다른 일을 시도했지만 여기에 코드 내 가장 최근의 반복 (난 그냥 배열 전달하는 일에, 그래서 아직 여기에 실제 행렬 곱셈이 아니다 얻을려고)입니다 :

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 Creates the initial matrix
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 Creates the initial matrix
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 

I 해요 여전히 점점 오류 :이 작업을 수행하는 방법은 두 가지가 있습니다

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

여기서 제기하는 몇 가지 문제가 있지만 대부분의 오류를 제공 한 코드 샘플과 일치시킬 수 없습니다. – francescalus

+1

저는 Fortran77에 자신을 국한시키는 것이 아니라고 생각합니다. 당신은 f77을 가진 배열을 리턴 할 수 없다. 그리고 당신이 이미 금세기의 컴파일러를 사용하고 있다는 것을 나타내는 에러가 없다는 사실. 태그와 제목을 편집해야합니다. – agentp

답변

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)

+0

답장을 보내 주셔서 감사합니다. MATMULT 함수를 호출 할 때도 여전히 동일한 문제가 있습니다. 어떻게 부르죠? MATMULT = MATMULT (X, Y, Z) 또는 MAT = MATMULT (X, Y, Z) 또는 MATMULT (X, Y, Z)를 시도하면 오류 : 분류 불가능 문을 얻습니다. 함수가 정의되어 있습니다. 작동하지 않는 함수를 호출 한 후 출력을 사용하는 것입니다. – user3290922

+2

나는 '의도'가 아니라 '의도'라고 생각합니다 (http://en.wikibooks.org/wiki/Fortran/Fortran_procedures_and_functions#Intent). –

+0

@KyleKanos, 수정 됨. – Ilmirus

1

것은이 없음 FORTRAN 77 FORTRAN 77. Fortran 90/95/2003은 사용하기 쉽고, 강력하며, 프로그래머가 실수를 찾도록 도와줍니다. gfortran은 훌륭한 오픈 소스 컴파일러입니다.

다음은 Fortran 95에서 유사한 프로그램/함수 인 벡터 교차 제품을 구현하는 함수의 예입니다.이 예제는 두 개의 벡터를 받고 하나의 벡터를 반환하는 함수와 함께 동일한 파일에있는 함수와 프로그램을 보여줍니다 (다른 접근법이 있음). 예 : Computing the cross product of two vectors in Fortran 90

+0

고마워요, 그게 제가 들었던 것입니다. 내가 gfortran 컴파일러를 사용하고 있지만 불행히도 Fortran77을 사용하도록 지정되었으므로 선택의 여지가 없습니다 ... 링크를 제공해 주셔서 감사합니다 :) – user3290922

0

질문에 몇 가지 문제점이 언급되어 있습니다. M. S. B.와 Ilmirus의 답에 주어진 바와 같이 최근 Fortran 방언을 사용하면 작업이 향상 ​​될 것입니다. 그리고 실제로는 implicit none을 사용해야합니다 (Fortran 77의 경우에도 많은 컴파일러가이를 지원하고 확장자로 소문자를 지원합니다).

개념적 부분에 와서, 나는 당신이 당신의 학습을 계속할 필요가 있다고 말해야 만합니다. 당신이 반환 행렬 제품을 기능을하려는 경우, 당신은 z 오히려 스칼라보다 real z(2,2) 메인 프로그램에서

z = matmult(x,y) 

얹는

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

, 뭔가를해야합니다 blah 예를 들어 귀하의 결과입니다.

서브 루틴에 와서 실제로는 문제가 있습니다. real subroutine matmult(x,y,z)에는 real이 필요하지 않습니다. 그런 다음 mat0을 업데이트하려는 곳인 call matmult(mat0, mat0, mat0)을 호출하면 별칭 문제가 있는지 묻습니다. call matmult(x,y,z)은 서브 루틴 계산에서 넣은 "결과 저장"을 수행합니다. Ilmirus가 제시 한대로 intent을 사용하면 프로그래머가 원하는 동작에 대한 좋은 지침이됩니다.

마지막으로, 당신은 단지 행렬로 AB을 곱한 C에 저장하는 결과를 얻으려면 : 나중에보다 F77 컴파일러 C = matmul(A,B)을 사용합니다.

그러나 Fortran 77에서는 배열 결과를 반환하지 않으므로 서브 루틴 접근 방법이 필요합니다. 귀하의 편집에 대응 : matmult(X,Y)에 참조가 오류를 야기 할 수 있도록

REAL MATMULT(2,2) 

는, 배열, 함수가 아닌 matmult를 선언한다.