2014-10-31 60 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移動到源文件的末尾,然後整理剩餘的錯誤。