【问题标题】:Recursive Fortran function return array?递归Fortran函数返回数组?
【发布时间】:2015-10-23 18:23:48
【问题描述】:

我对 Fortran 比较陌生(使用 90),还没有找到任何文献回答这个问题,所以我想我会在这里问 SO:我正在尝试写将返回一个数组的递归函数。

我的最终目标是在 Fortran 中编写自己的 FFT,而无需通过 C fftw 并使用“C to Fortran”包;我知道有一些方法可以在不使用递归函数的情况下执行此操作,但我仍然想知道递归函数是否能够返回数组。

作为练习,我尝试编写一个程序,该程序接受一个自然数,递归地计算斐波那契数列并返回索引到参数整数的斐波那契数列表。使用相同的算法,我在 Matlab 中编写了这个函数,它可以工作,但是在 Fortran 90 中编写时出现语义错误:

recursive function Fibbo(l)
    integer, INTENT(IN) :: l
    integer, dimension(l)  :: x

    integer, dimension(l) :: Fibbo

    if ( l == 1 ) then
        x = 1
    else if ( l == 2 ) then
        x(1) = 1
        x(2) = 1
    else
        x(1:l-1) = Fibbo(l-1)
        x(n) = x(l-1) + x(l-2)
    end if

Fibbo = x  
end function

它会编译得很好,除了输出没有问题:(尝试调用 ell = 3 时)

Enter an integer:
3
 -1610612736
  1342177280
           0

每次都有不同的输出,并且有这样的输出,我猜测内存分配存在问题,或者类似的问题,但就像我说的那样,我在网上找不到任何解决递归函数返回数组的文献。或许做不到?

附:它会在调用 Fibbo(1)、Fibbo(2)、rest 时输出正确的列表——即 1, [1 1]。

编辑: 附言如果重要的话,我正在优胜美地使用 gfortran 进行编译

编辑: 感谢您指出错误,但是尝试重铸输出并没有解决它:

recursive function Fibbo(l) result(x)
    integer, INTENT(IN) :: l
    integer, dimension(l)  :: x

    if ( l == 1 ) then
        x = 1
    else if ( l == 2 ) then
        x(1) = 1
        x(2) = 1
    else
        x(1:l-1) = Fibbo(l-1)
        x(n) = x(l-1) + x(l-2)
    end if

end function

这仍然会给 ell > 2 带来错误。

【问题讨论】:

  • 函数内部Fibbo(l-1) 不是对函数的引用,而是(未定义的)结果数组。看,也许,stackoverflow.com/q/31061507
  • 函数在调用它的范围内是否有显式接口?如果没有,它需要一个。
  • Fortran 规则 1:始终在每个作用域单元中使用 implicit none。这样,您尤其是避免了不需要的变量的无意动态声明,例如语句x(n) = x(l-1) + x(l-2) 中的n。投票结束,这是一个拼写错误。
  • n 确实是问题所在,将函数放在以implicit none 开头的模块中。我还建议重新制定你的 FFT 计划,如果你需要转换来进行严肃的工作,而不仅仅是为了好玩。有可用的 Fortran 库,很难达到它们的质量和性能。
  • @IanH:是的,当时应该在stackoverflow.com/questions/24337413/… 参考您自己的答案。另一方面,过度使用implicit none 比使用不足的罪过要轻。

标签: arrays function recursion fortran fibonacci


【解决方案1】:

问题出在这一行:

x(n) = x(l-1) + x(l-2)

您分配给数组x 的元素n 的位置。问题是 n 是一个未初始化的整数类型的隐式变量(因为您没有声明任何名为 n 的变量)。您尚未为 n 分配值,并且正在访问它,从而使其成为不合格程序。

如 cmets 中所述,使用 'implicit none' 被认为是最佳实践,当您无意中使用未声明的变量时会导致编译器错误。例如gfortran 5.2 会抱怨:

        x(n) = x(l-1) + x(l-2)
          1
Error: Symbol ‘n’ at (1) has no IMPLICIT type

如果您将 n 修复为 l 并确保您的函数具有显式接口(例如,通过将其放入模块中),您的代码就可以工作。

出于演示目的,这是我对您的代码所做的:

module fib
  implicit none
contains
  recursive function Fibbo(l) result(x)
    implicit none
    integer, INTENT(IN) :: l
    integer, dimension(l)  :: x
    if ( l == 1 ) then
       x = 1
    else if ( l == 2 ) then
       x(1) = 1
       x(2) = 1
    else
       x(1:l-1) = Fibbo(l-1)
       x(l) = x(l-1) + x(l-2)
    end if
  end function Fibbo
end module fib

program test
  use fib
  implicit none
  print *, Fibbo(10)
end program test

哪个会输出

1       1       2       3       5       8      13      21      34      55

【讨论】:

  • 知道了!太感谢了!这也澄清了我对“隐式无”的宗教使用目的的疑惑!
猜你喜欢
  • 2015-04-27
  • 2021-08-14
  • 2019-04-25
  • 2022-01-16
  • 1970-01-01
  • 2013-08-07
  • 2020-04-08
相关资源
最近更新 更多