2011-06-28 67 views
5

我想計算Fortran 90中兩個向量的叉積。例如,用詞來說,(1,2,3)和(4,5)的叉積,6)在笛卡爾座標系中是(-3,6,-3)。我寫了下面的代碼(主程序之後函數定義):計算Fortran 90中兩個向量的叉積90

PROGRAM crosstest 
    IMPLICIT NONE 

    INTEGER, DIMENSION(3) :: m, n 
    INTEGER, DIMENSION(3) :: cross 
    INTEGER, DIMENSION(3) :: r 

    m=(/1, 2, 3/) 
    n=(/4, 5, 6/) 
    r=cross(m,n) 

END PROGRAM crosstest 

FUNCTION cross(a, b) 
    INTEGER, DIMENSION(3) :: cross 
    INTEGER, DIMENSION(3), INTENT(IN) :: a, b 

    cross(1) = a(2) * b(3) - a(3) * b(2) 
    cross(2) = a(3) * b(1) - a(1) * b(3) 
    cross(3) = a(1) * b(2) - a(2) * b(1) 
END FUNCTION cross 

但是,我得到一個錯誤信息:

crosstest.f90:10.9: 

    r=cross(m,n) 
     1 
Error: Rank mismatch in array reference at (1) (2/1) 

,其中10號線是r=cross(m,n)。看來我必須錯誤地指定尺寸。這裏有一些想法,我有:

  1. 也許功能cross的主程序的聲明應該是簡單的整型變量,而不是一個1by3整數數組。所以我試着刪除主程序中INTEGER, DIMENSION(3) :: cross行中的, DIMENSION(3)。但我收到一條錯誤消息:

    crosstest.f90:10.4: 
    
        r=cross(m,n) 
        1 
    Error: The reference to function 'cross' at (1) either needs an 
    explicit INTERFACE or the rank is incorrect 
    

    所以這可能更糟糕。

  2. Web上的一些(但不是全部)Fortran函數示例在主程序中的函數聲明後放置了一條EXTERNAL語句。所以我試圖在主程序中的聲明塊後放置一行EXTERNAL cross。我收到一條錯誤消息:

    crosstest.f90:8.16: 
    
        EXTERNAL cross 
           1 
    Error: EXTERNAL attribute conflicts with DIMENSION attribute at (1) 
    

    所以這看起來也不正確。

  3. Web上的一些(但不是全部)Fortran函數示例在函數定義的倒數第二行上放置了一條RETURN語句。我試過這個,但是我得到原來的排名不匹配錯誤:

    crosstest.f90:10.9: 
    
        r=cross(m,n) 
         1 
    Error: Rank mismatch in array reference at (1) (2/1) 
    

    所以這不能解決問題。

你能幫我看看我的錯誤嗎?

回答

19

最好的做法是將你的程序(子程序和函數)放在一個模塊中,然後從主程序或其他程序中「使用」該模塊。您無需從同一模塊的其他程序中「使用」該模塊。這將使過程的接口顯式化,以便調用程序或過程「知道」參數的特性......它允許編譯器檢查兩邊參數之間的一致性......調用者和被調用者... this消除了很多錯誤。

在語言標準之外,但在實踐中是必要的:如果您使用一個文件,請將模塊放置在使用它的主程序之前。否則編譯器將不知道它。所以:

module my_subs 

implicit none 

contains 

FUNCTION cross(a, b) 
    INTEGER, DIMENSION(3) :: cross 
    INTEGER, DIMENSION(3), INTENT(IN) :: a, b 

    cross(1) = a(2) * b(3) - a(3) * b(2) 
    cross(2) = a(3) * b(1) - a(1) * b(3) 
    cross(3) = a(1) * b(2) - a(2) * b(1) 
END FUNCTION cross 

end module my_subs 


PROGRAM crosstest 
    use my_subs 
    IMPLICIT NONE 

    INTEGER, DIMENSION(3) :: m, n 
    INTEGER, DIMENSION(3) :: r 

    m= [ 1, 2, 3 ] 
    n= [ 4, 5, 6 ] 
    r=cross(m,n) 
    write (*, *) r 

END PROGRAM crosstest 
+0

非常感謝您的時間! – Andrew

+3

+ 1使用'[1,2,3]'代替(更醜陋)'(\ 1,2,3 \)'。 –

5

這是怎樣的一個遲到的回答的,但因爲我偶然發現了這一點,並沒有真正的解釋又爲什麼出現你的錯誤,我想誰絆倒後我會增加對別人解釋這個問題:

在你的程序中,你定義了一個名爲cross的數組,其排名爲1.然後你調用你定義的cross函數。由於cross函數沒有明確的接口(請參閱M.S.B的答案),編譯器此時不知道它。它所知道的是你聲明的數組。如果編寫r = cross(m, n),編譯器認爲您要訪問數組cross的位置(m,n)處的元素。由於該數組是1級的,但是你提供的兩個參數,你的錯誤

rank mismatch in array reference at (1) (2/1) 

這意味着你提供的兩個座標時,編譯器要求之一。

+0

謝謝。這就說得通了。我相應地編輯了答案。 – toster