473,661 Members | 2,506 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Why is recursion so slow?

Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?

is the recursive definition counting fib 1 to fib x-1 for every x? is
that what lazy evaluation in functional languages avoids thus making
recursive versions much faster?
is recursive fibonacci in haskell as fast as an imperative solution in
a procedural language?

def fibr(nbr):
if nbr 1:
return fibr(nbr-1) + fibr(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0

def fibf(n):
sum=0
a=1
b=1
if n<=2: return 1
for i in range(3,n+1):
sum=a+b
a=b
b=sum
return sum
i found a version in Clojure that is superfast:
(def fib-seq
(concat
[0 1]
((fn rfib [a b]
(lazy-cons (+ a b) (rfib b (+ a b)))) 0 1)))

(defn fibx [x]
(last (take (+ x 1) fib-seq)))

(fibx 12000) is delivered instantly. is it using lazy evaluation?
Jun 29 '08 #1
10 5481

Quoting slix <no**********@y ahoo.se>:
Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?
The problem is not with 'recursion' itself, but with the algorithm:

def fibr(nbr):
if nbr 1:
return fibr(nbr-1) + fibr(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0
If you trace, say, fibr(5), you'll find that your code needs to compute fibr(4)
and fibr(3), and to compute fibr(4), it needs to compute fibr(3) and fibr(2). As
you can see, fibr(3), and it whole subtree, is computed twice. That is enough to
make it an exponential algorithm, and thus, untractable. Luckily, the iterative
form is pretty readable and efficient. If you must insist on recursion (say,
perhaps the problem you are solving cannot be solved iteratively with ease), I'd
suggest you to take a look at 'dynamic programming', or (easier but not
necesarily better), the 'memoize' disgn pattern.

is the recursive definition counting fib 1 to fib x-1 for every x?
Yes - that's what the algorithm says. (Well, actually, the algorithm saysto
count more than once, hence the exponential behaviour). The memoize patter could
help in this case.
is
that what lazy evaluation in functional languages avoids thus making
recursive versions much faster?
Not exactly... Functional languages are (or should be) optimized for recursion,
but if the algorithm you write is still exponential, it will still take along time.
is recursive fibonacci in haskell as fast as an imperative solution in
a procedural language?
[...]
i found a version in Clojure that is superfast:
I've seen the haskell implementation (quite impressive). I don't know Clojure
(is it a dialect of Lisp?), but that code seems similar to the haskell one. If
you look closely, there is no recursion on that code (no function calls).The
haskell code works by defining a list "fib" as "the list that starts with0,1,
and from there, each element is the sum of the element on 'fib' plus the element
on 'tail fib'). The lazy evaluation there means that you can define a list based
on itself, but there is no recursive function call.

Cheers,

(I'm sleepy... I hope I made some sense)

--
Luis Zarrabeitia
Facultad de Matemática y Computación, UH
http://profesores.matcom.uh.cu/~kyrie
Jun 29 '08 #2


slix wrote:
Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?
The comparison below has nothing to do with recursion versus iteration.
(It is a common myth.) You (as have others) are comparing an
exponential, O(1.6**n), algorithm with a linear, O(n), algorithm.

def fibr(nbr):
if nbr 1:
return fibr(nbr-1) + fibr(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0
This is exponential due to calculating fib(n-2) twice, fib(n-3) thrice,
fib(n-4) 5 times, fir(n-5) 8 times, etc. (If you notice an interesting
pattern, you are probably correct!) (It returns None for n < 0.)
If rewritten as iteratively, with a stack, it is still exponential.
def fibf(n):
sum=0
a=1
b=1
if n<=2: return 1
for i in range(3,n+1):
sum=a+b
a=b
b=sum
return sum
This is a different, linear algorithm. fib(i), 0<=i<n, is calculated
just once. (It returns 1 for n < 0.) If rewritten (tail) recursively,
it is still linear.

In Python, an algorithm written with iteration is faster than the same
algorithm written with recursion because of the cost of function calls.
But the difference should be a multiplicative factor that is nearly
constant for different n. (I plan to do experiments to pin this down
better.) Consequently, algorithms that can easily be written
iteratively, especially using for loops, usually are in Python programs.

Terry Jan Reedy

Jun 29 '08 #3
On Sun, Jun 29, 2008 at 1:27 AM, Terry Reedy <tj*****@udel.e duwrote:
>

slix wrote:
>>
Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?

The comparison below has nothing to do with recursion versus iteration. (It
is a common myth.) You (as have others) are comparing an exponential,
O(1.6**n), algorithm with a linear, O(n), algorithm.
FWIW, though, it's entirely possible for a recursive algorithm with
the same asymptotic runtime to be wall-clock slower, just because of
all the extra work involved in setting up and tearing down stack
frames and executing call/return instructions. (If the function is
tail-recursive you can get around this, though I don't know exactly
how CPython is implemented and whether it optimizes that case.)
Jun 29 '08 #4
In case anyone is interested...

# Retrieved from: http://en.literateprograms.org/Fibon...n)?oldid=10746

# Recursion with memoization
memo = {0:0, 1:1}
def fib(n):
if not n in memo:
memo[n] = fib(n-1) + fib(n-2)
return memo[n]

# Quick exact computation of large individual Fibonacci numbers

def powLF(n):
if n == 1: return (1, 1)
L, F = powLF(n/2)
L, F = (L**2 + 5*F**2) >1, L*F
if n & 1:
return ((L + 5*F)>>1, (L + F) >>1)
else:
return (L, F)

def fib(n):
return powLF(n)[1]
Jun 30 '08 #5
Dan Upton a écrit :
On Sun, Jun 29, 2008 at 1:27 AM, Terry Reedy <tj*****@udel.e duwrote:
>>
slix wrote:
>>Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?
The comparison below has nothing to do with recursion versus iteration. (It
is a common myth.) You (as have others) are comparing an exponential,
O(1.6**n), algorithm with a linear, O(n), algorithm.

FWIW, though, it's entirely possible for a recursive algorithm with
the same asymptotic runtime to be wall-clock slower, just because of
all the extra work involved in setting up and tearing down stack
frames and executing call/return instructions. (If the function is
tail-recursive you can get around this, though I don't know exactly
how CPython is implemented and whether it optimizes that case.)
By decision of the BDFL, based on the argument that it makes debugging
harder, CPython doesn't optimize tail-recursive calls.
Jun 30 '08 #6
On 2008-06-29, slix <no**********@y ahoo.sewrote:
Recursion is awesome for writing some functions, like searching trees
etc but wow how can it be THAT much slower for computing fibonacci-
numbers?
Try the following recursive function:

def fib(n):

def gfib(a, b , n):
if n == 0:
return a
else:
return gfib(b, a + b, n - 1)

return gfib(0, 1, n)

--
Antoon Pardon
Jul 1 '08 #7
Luis Zarrabeitia <ky***@uh.cuwro te:
is that what lazy evaluation in functional languages avoids thus
making recursive versions much faster?

Not exactly... Functional languages are (or should be) optimized for recursion,
but if the algorithm you write is still exponential, it will still
take a long time.
Actually I think functional language are likely to perform
memoization. By definition any function in a functional language will
always produce the same result if given the same arguments, so you can
memoize any function.

See here for a python memoize which makes the recursive algorithm run
fast...

http://aspn.activestate.com/ASPN/Coo...n/Recipe/52201

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jul 1 '08 #8
On 1 juil, 22:46, Nick Craig-Wood <n...@craig-wood.comwrote:
(snip)
By definition any function in a functional language will
always produce the same result if given the same arguments,
This is only true for pure functional languages.

I know you know it, but someone might think it also applies to unpure
FPLs like Common Lisp.

(snip)
Jul 1 '08 #9
Nick Craig-Wood wrote:
[snip]
By definition any function in a functional language will
always produce the same result if given the same arguments, so you can
memoize any function.
Ah, so that's why time.time() seems to be stuck... ;)

Rich

Jul 1 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
3415
by: Peri | last post by:
I'm trying to create Python parser/interpreter using ANTLR. Reading grammar from language refference I found: or_expr::= xor_expr | or_expr "|" xor_expr For me it looks like infinite recursion. And so it says ANTLR. Maybe I don't understand EBNF notation. For me it should look like this. or_expr::= xor_expr | xor_expr "|" xor_expr and in ANTLR grammar file like this:
6
4212
by: Thomas Mlynarczyk | last post by:
Hi, Say I have an array containing a reference to itself: $myArray = array(); $myArray =& $myArray; How can I, looping iteratively through the array, detect the fact that $myArray will "take" me to where I have already been? The print_r() and var_dump() functions print *RECURSION* in such a case (though only after the "second round"). Setting a flag seems to be the only solution, but I don't want to modify the array in question - I...
43
4149
by: Lorenzo Villari | last post by:
I've tried to transform this into a not recursive version but without luck... #include <stdio.h> void countdown(int p) { int x;
75
5602
by: Sathyaish | last post by:
Can every problem that has an iterative solution also be expressed in terms of a recursive solution? I tried one example, and am in the process of trying out more examples, increasing their complexity as I go. Here's a simple one I tried out: #include<stdio.h> /* To compare the the time and space cost of iteration against
20
2986
by: athar.mirchi | last post by:
..plz define it.
30
8290
by: Jeff Bigham | last post by:
So, it appears that Javascript has a recursion limit of about 1000 levels on FF, maybe less/more on other browsers. Should such deep recursion then generally be avoided in Javascript? Surprisingly, deep recursion actually isn't that slow for what I'm doing. Programming this task recursively is so much more straightforward to me, but currently I'm forced to use an ugly hack to avoid going over the 1000 level limit. Of course, it could...
0
986
by: Jean-Paul Calderone | last post by:
On Sun, 29 Jun 2008 10:03:46 -0400, Dan Upton <upton@virginia.eduwrote: CPython doesn't do tail call elimination. And indeed, function calls in Python have a much higher fixed overhead than iteration. Jean-Paul
2
1327
by: B | last post by:
Hey I found some (VERY) old C++ code of mine that recursively built a tree of the desktop window handles (on windows) using: (they are stored in an STL vector) void FWL(HWND hwnd, int nFlag) // Recursive Function { hwnd = GetWindow(hwnd, nFlag); if(hwnd == NULL) return; AddWnd(hwnd);
35
4715
by: Muzammil | last post by:
int harmonic(int n) { if (n=1) { return 1; } else { return harmonic(n-1)+1/n; } } can any help me ??
0
8343
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8856
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8762
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8545
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8633
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7365
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4347
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2762
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1992
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.