【问题标题】:Defining a function returning an array定义返回数组的函数
【发布时间】:2014-09-14 15:48:27
【问题描述】:

我有以下代码:

    Program function_as_an_array
    implicit none
    integer:: i
    integer, parameter:: N=10
    real*8:: x(N),y(N),f(N)

    do i=1,N
      x(i)=float(i)
    end do

    call func(f,N,x)

    open(unit=20, file='test.dat')
    do i=1,N
      y(i)=f(i)
      write(20,*) x(i),y(i) 
    end do
    close(20)
    Stop 
    End Program function_as_an_array


    Subroutine func(f,N,x)
    implicit none
    integer i,N
    real*8:: x(N),f(N) 

    do i=1,N
       f(i)=x(i)**2
    end do

    end Subroutine func

我想让程序确实适合 “函数作为一个数组”,即我想用function f 替换Subroutine func 并获得相同的结果(在主程序中,我希望保留一个类似y=f(x,N) 的语句)。我该怎么做?

【问题讨论】:

    标签: arrays function fortran fortran90


    【解决方案1】:

    函数返回数组没有问题,就像this question and answer:主要问题是你需要函数在模块中(或在程序中contained),以便有一个自动显式接口: (编辑添加:或者像 Alexander Vogt 的回答一样明确定义界面)

    module functions
    contains
    
        function func(N,x)
        implicit none
        integer, intent(in) :: N
        double precision, intent(in) :: x(N)
        double precision, dimension(N) :: func
    
        integer :: i
    
        do i=1,N
           func(i)=x(i)**2
        end do
    
    end function func
    
    end module functions
    
    Program function_as_an_array
    use functions
    implicit none
    integer:: i
    integer, parameter:: N=10
    double precision:: x(N),y(N)
    
    do i=1,N
      x(i)=float(i)
    end do
    
    y = func(N,x)
    
    open(unit=20, file='test.dat')
    do i=1,N
      write(20,*) x(i),y(i)
    end do
    close(20)
    Stop
    End Program function_as_an_array
    

    但是请注意,这种函数 - 对数组中的每个元素应用相同的操作 - 使用 Fortran elemental 函数可以更好地完成,定义为简单地在标量上工作,Fortran 将自动将其映射到所有元素给你一个数组:

    module functions
    contains
    
        elemental double precision function f(x)
        implicit none
        double precision, intent(in) :: x
    
        f = x**2
    
        end function f
    
    end module functions
    
    Program function_as_an_array
        use functions
        implicit none
        integer:: i
        integer, parameter:: N=10
        double precision:: x(N),y(N)
    
        do i=1,N
          x(i)=float(i)
        end do
    
        y = f(x)
    
        open(unit=20, file='test.dat')
        do i=1,N
          write(20,*) x(i),y(i)
        end do
        close(20)
        Stop
    End Program function_as_an_array
    

    这样做的好处是它现在可以自动处理标量和任何等级的数组。只要有可能,最好让编译器为您完成工作。

    【讨论】:

    • 基本函数...不错 ;-)
    【解决方案2】:

    这对我有用:

    Program function_as_an_array
    implicit none
    integer:: i
    integer, parameter:: N=10
    real*8 :: x(N),y(N),f(N)
    interface func
      function func(x,N) result(f)
        implicit none
        integer N
        real*8:: x(N),f(N) 
      end function
    end interface
    
    do i=1,N
      x(i)=float(i)
    end do
    
    f = func(x,N)
    
    open(unit=20, file='test.dat')
    do i=1,N
      y(i)=f(i)
      write(20,*) x(i),y(i) 
    end do
    close(20)
    Stop 
    End Program function_as_an_array
    
    
    function func(x,N) result(f)
    implicit none
    integer i, N
    real*8:: x(N),f(N) 
    
    do i=1,N
       f(i)=x(i)**2
    end do
    
    end function
    

    你需要:

    • result 用于数组值返回变量[编辑] 或将func 指定为real*8:: func(N)。有关详细信息,请参阅 cmets。
    • 外部函数使用显式接口(或具有隐式接口的模块,请参阅 Jonathan Dursi 的回答)

    然后,可以直接将函数的返回值赋值给数组。

    【讨论】:

    • 在这种情况下你正式需要使用result吗?我通常没有,到目前为止它对我来说一直有效——但仅仅因为 gfortran/ifort 允许它并不意味着它不是标准所要求的,而且我从来没有理由仔细研究过。
    • 前段时间我遇到了没有定义的问题......从那以后我就养成了这样做的习惯。
    • 嗯 - 我应该看看标准是怎么说的。我注意到也建议使用这种方法here。无论如何我喜欢结果语法,我只是从来没有完全养成使用它的习惯。
    • 好吧,我在标准(第 12.6.2.2 章)中找不到任何强制一种或另一种形式的内容。我会改变我的答案...
    • @AlexanderVogt 和@JonathanDursi:感谢你们俩。并且在 cmets 中进行了非常互动的讨论。我不知道resultelemental。不过,我更倾向于@Jonathan,因为它不需要辅助功能func
    猜你喜欢
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多