2011-06-28 64 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