Fibonacci递归函数需要永远

时间:2015-05-23 03:20:44

标签: recursion fortran fibonacci

我想得到Fibonacci序列的第48个元素 我可以存储64位整数。我正在使用一个递归子程序,但它需要永远完成。如果有人能够找到我的递归子程序的问题,我将非常感激。

Integer (Int8) :: n
Integer (Int64) :: fib64
n = Int (48, Int8)
Call fibonacci_genr (fib64, n) 

这是我的递归子程序

Recursive                  &
Subroutine fibonacci_genr  &
(                        &
  fb, n                  &
)

Integer (Int64), Intent (Out) :: fb
Integer (Int8), Intent (In) :: n

    Integer (Int64) :: fb1, fb2
    If (n < 2) Then 
      fb = Int (n, Int64) 
    Else 
      Call fibonacci_genr (fb1, n-1)
      Call fibonacci_genr (fb2, n-2)
      fb = fb1 + fb2
    End If
End Subroutine fibonacci_genr

5 个答案:

答案 0 :(得分:1)

Appologies我不知道fortran我会尽我所能向你展示如何在javascript中加速它并且我在Fortran解决方案中表现最好

ggtern(data = df,aes(x = c,y = a,z = b)) +
  stat_density2d(geom = "polygon", n = 400, aes(fill = ..level.., weight = d, alpha = abs(..level..))) +
  geom_density2d(aes(weight = d,color = ..level..), n = 400) +
  geom_point(aes(fill = d),color = "black",size = 5,shape = 21) +
  geom_text(aes(label = id),size = 3) +
  labs(x = "X (%)",y = "Y (%)",z = "Z (%)",title = "Title", size = 3) +
  scale_fill_gradient2(low = "green", mid = "yellow", high = "red", midpoint = 10) +
  scale_color_gradient2(low = "green", mid = "yellow", high = "red", midpoint = 10) +
  theme_custom(base_size = 12, base_family = "", col.T = "black", col.L = "black", col.R = "black", col.BG = "white") +
  tern_anticlockwise() +
  tern_limits(breaks = seq(0.1,1,by = 0.1)) + #AFFECT ALL SCALES
  theme(axis.tern.arrowstart = 0.4,axis.tern.arrowfinish = 0.6) +
  theme(legend.justification = c(0,1), legend.position = c(0,1)) +
  guides(fill = guide_colorbar(order = 1), alpha = guide_legend(order = 2), color = "none") +
  labs( title = "Ternary filled contour plot", fill = "Value, V",alpha = "|V - 0|")

这是备忘的fortran

var memo = [];
function fib(n) {
    if (memo[n-1]) { //check to see if you already calculated the answer
        return memo[n-1];
    }
    memo[n-1] = n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
    return memo[n-1];
}

答案 1 :(得分:1)

鉴于Int8=1Int64=8以及显式接口,gfortran4.7.2抱怨

call fibonacci_genr( fb1, n-1 )
                          1
Error: Type mismatch in argument 'n' at (1); passed INTEGER(4) to INTEGER(1)

如果实际参数被强制转换为Int8

Call fibonacci_genr (fb1, int( n-1, Int8 ) )
直接使用

Int8文字(感谢@francescalus)

Call fibonacci_genr (fb1, n - 1_Int8 )

代码似乎工作正常。但我认为使用integer :: n而不是integer(Int8) :: n要简单得多,因为n没有溢出....

BTW我还测量了n = 048调用此例程的时间。在Xeon2.6GHz(x86_64)+ gfortran4.7.2 -O2上是91秒。如果子程序被函数替换,则时间减少到72秒。为了比较,我还在Julia中尝试了以下代码

function fibo( n::Int )  # Int defaults to Int64
    if n <= 1
        return n
    else
        return fibo( n-1 ) + fibo( n-2 )
    end
end

for inp = 0:48
    println( fibo( inp ) )
end

花了118秒,这对于这次递归非常有用。另一方面,直接迭代(没有递归调用)当然是超快的,只需<0.001秒。

答案 2 :(得分:1)

此解决方案为您提供线性时间的斐波那契数字(调用次数==斐波纳契数字-2,数字1和2只调用1次)。这是通过使用递归函数来完成的,该函数返回序列的两个数字,以便每个调用可以计算下一个数字并重新使用前一个数字作为其返回值。如果你想调用它只接收新的数字,这确实需要一个包装函数,但这是减少递归的一小部分。

以下是功能:

  integer(kind=int64) pure function fibonacci(n)
    use iso_fortran_env
    implicit none
    integer, intent(in) :: n
    integer(kind=int64), dimension(2) :: fibo

    fibo = fib(int(n,int64))
    fibonacci = fibo(1)
  end function fibonacci

  recursive pure function fib(n) result(ret)
    use iso_fortran_env
    implicit none
    integer(kind=int64), intent(in) :: n
    integer(kind=int64), dimension(2) :: tmp,ret

    if (n == 1_int64) then
       ret = [1_int64, 0_int64]
    else if (n == 2_int64) then
       ret = [1_int64, 1_int64]
    else
       tmp = fib(n-1)
       ret = [sum(tmp), tmp(1)]
    end if
  end function fib

使用这些函数计算fibonacci(48)的时间可以忽略不计。

答案 3 :(得分:0)

像这样递归地计算Fibonacci会导致重复计算Recursion vs. Iteration (Fibonacci sequence)。为避免这种情况,请使用迭代算法。

答案 4 :(得分:0)

这是用Python编写的(同样没有FORTRAN)。

def f(a):
  if (a < 2):
    return a;
  return _f(a-2, 2, 1)

def _f(a, n1 , n2) :
  if(a==0) :
    return n1+n2
  return _f(a-1, n1+n2, n1)

每个数字只计算一次而不是多次。 _f是一个私人函数f是你调用的函数,

注意:这仍然是递归的,但只会调用自己48次(N次)