[英]Fibonacci Recursive function takes forever
我想獲得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
應用我不知道fortran我會盡我所能向你展示如何在javascript中加速它以及我在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];
}
這是備忘的fortran
Integer (Int64) :: memo(48) = 0
Integer (Int64), Intent (Out) :: fb
Integer (Int8), Intent (In) :: n
Integer (Int64) :: fb1, fb2
If (memo(n) > 1) Then ! if its in the array we just use that value
fb = memo(n)
Else If (n <= 2) Then
memo(n) = Int (1, Int64)
fb = memo(n)
Else
Call fibonacci_genr (fb1, n-1)
Call fibonacci_genr (fb2, n-2)
memo(n) = fb1 + fb2
fb = memo(n)
End If
End Subroutine fibonacci_genr
鑒於Int8=1
和Int64=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
....
順便說一下,我還測量了n = 0
到48
時調用此例程的時間。 在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次呼叫)。 這是通過使用遞歸函數來完成的,該函數返回序列的兩個數字,以便每個調用可以計算下一個數字並重新使用前一個數字作為其返回值。 如果你想調用它只接收新的數字,這確實需要一個包裝函數,但這是減少遞歸的一小部分犧牲。
以下是功能:
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)
的時間可以忽略不計。
像這樣遞歸地計算斐波那契導致重復計算遞歸與迭代(斐波那契序列) 。 為避免這種情況,請使用迭代算法。
這是用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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.