2014-10-31 63 views
0

我期待传递一个语句函数在另一个函数中进行评估,这可能吗?我想要一个可以在数值上集成一般函数的函数。在我真正的问题中还有其他值,所以我不想有一个外部函数。Fortran传递语句函数到函数

编辑2014年11月1日02:22 GMT

有一对情侣在代码@IanH投入的错误。这是我照顾的错误后,其运作的代码。


program trapezoidZ 
    implicit none 

    ! main program global variables and constants here. 

    call main 
contains 
subroutine main 
    real :: u, integral1 
    integer :: i 
    integer, parameter :: n = 5000 
    ! delete declaration of trapezoid_integration and f. 

    integral1 = trapezoid_integration(TrigSin, n, 0., 3.14159/2.0) 

    write (*,*) "I - Trap = ",1 - integral1 
end subroutine main 

function my_f(u) 
    real :: my_f 
    real, intent(in) :: u 

    my_f = (u**4)*EXP(u)/((EXP(u)-1.0)**2) 
end function my_f 

function TrigSin(u) result(my_f) 
    real :: my_f 
    real, intent(in) :: u 

    my_f = sin(u) 
end function TrigSin 

function trapezoid_integration (f, n, start_val, end_val) result (integral) 
    ! delete declaration of integrand (assuming you have it). 
    procedure(my_f) :: f 

    integer :: n 
    real :: start_val, end_val 
    real :: integral,u,h 
    integer :: i 

    integral = 0.0 

    do i=0,n 
     u = start_val + ((end_val - start_val)*i)/n 

     ! implement Eqn G.4 
     if ((i.eq.0).or.(i.eq.n)) then 
      integral = integral+integrand(f, u) 
     else 
      integral = integral+(2.0*integrand(f, u)) 
     end if 

    end do 

    h=(end_val - start_val)/n 
    integral = (h/2.0)*integral 

end function trapezoid_integration 

function integrand(f, x) result (value) 
    implicit none 
    real :: x 
    real :: value 
    real :: f 

    if (x .lt. 0.00001) then 
     x = 0.00001 
    end if 

    value = f(x) 
end function integrand 

end program trapezoidZ 

下面这个是原代码。不要使用


program trapezoidZ 
    implicit none 
    integer, parameter :: n = 10 
    real :: u, integral 
    integer :: i 
    real :: f, trapezoid_integration 

    f(u) = (u**4)*EXP(u)/((EXP(u)-1.0)**2) 

    integral = trapezoid_integration(f, n, 0.2, 3.0) 
    write (*,*) '#trapezoidal integration = ',integral 

end program trapezoidZ 

function trapezoid_integration(f, n, start_val, end_val) 
    implicit none 
    integer :: n 
    real :: start_val, end_val 
    real :: f 
    real :: integral,u,h 
    integer :: i 

    integral = 0.0 

    do i=0,n 
    u = start_val + ((end_val - start_val)*i)/n 

    ! implement Eqn G.4 
    if ((i.eq.0).or.(i.eq.n)) then 
     integral = integral+integrand(f, u) 
    else 
     integral = integral+(2.0*integrand(f, u)) 
    end if 

    end do 

    h=(end_val - start_val)/n 
    integral = (h/2.0)*integral 

end subroutine trapezoid_integration 

function integrand(f, x) result (value) 
    implicit none 
    real :: x 
    real :: value 
    real :: f 

    if (x .lt. 0.00001) then 
    x = 0.00001 
    end if 

    value = f(x) 
end function integrand 

回答

4

它不是在标准Fortran允许的 - 声明函数是不是在允许的程序类型的约束C1235在2008年的Fortran列表。

但是,正如该约束所表明的那样,您不限于外部功能。从Fortran 90开始,实际参数可以是模块过程。从Fortran 2008开始,它可以是一个内部程序。

,提供紧凑和更强大的源的可能性:我不得不手工状态下的2008标准的草案

program trapezoidZ 
    implicit none 

    ! main program global variables and constants here. 

    call main 
contains 
    subroutine main 
    real :: u, integral 
    integer :: i 
    integer, parameter :: n = 10 
    ! delete declaration of trapezoid_integration and f. 

    integral = trapezoid_integration(my_f, 0.2, 3.0) 
    write (*,*) '#trapezoidal integration = ',integral 
    end subroutine main 

    function my_f(u) 
    real :: my_f 
    real, intent(in) :: u 

    my_f = (u**4)*EXP(u)/((EXP(u)-1.0)**2) 
    end function my_f 

    function trapezoid_integration(f, n, start_val, end_val) 
    ! delete declaration of integrand (assuming you have it). 
    procedure(my_f) :: f 
    ... 
    end function trapezoid_integration 

    function integrand(f, x) result (value) 
    ... 
    end function integrand 
end program trapezoidZ 
+0

此代码中有轻微的错误。我把最后的运行版本放在原文中。 – user1543042 2014-11-01 02:29:32

1

第12.6.4.4:

A statement function shall not be supplied as an actual argument.

所以我认为你不能按你想要的方式去做你想做的事。我想知道当你试图编译上面的代码时你的编译器告诉了你什么。当我在您的文章更正function trapezoid_integrationend subroutine trapezoid_integration之间的不匹配我的编译器(最近gfortran版)抱怨说,在通话中使用的f指着trapezoid_integration

Error: Statement function 'f' at (1) is not allowed as an actual argument

它抱怨其他的一些事情了。它可能指出,但没有,自1990年的标准以来,这些声明函数已经过时。

有多种方法可以修复您的程序,其中之一是使内部功能集成在一起,即将其声明在程序中的contains部分。实际上,我将包含您在程序中的这部分内显示的所有功能。在您编写代码时,trapezoid_integrationintegrand这两个过程都是外部过程,编译器在调用它们时无法检查它们的接口。重写f作为函数,并在end program处插入contains,并将end program移动到源文件的末尾,然后整理剩余的错误。