We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Calculating Fibonacci Sequence - Very Slow
Page Index Toggle Pages: 1
Calculating Fibonacci Sequence - Very Slow (Read 1966 times)
Calculating Fibonacci Sequence - Very Slow
Apr 3rd, 2010, 4:41am
 
Hey folks,

Trying to generate a Fibonacci sequence in processing, but I'm having trouble calculating the values quick enough - obviously the numbers can get quite large quite fast by recursion. Currently it is ouputting a variable frameRate that becomes progressively slower in a short amount of time, but ideally it would be once per second because I need my output to be metronomic. Is there any way of forcing processing to output the int result every second (maybe using second() instead of frameRate() might solve this issue actually...) - or if there's a less memory-intensive method of calculating the fibonacci sequence?

Here's my code:
Code:

/*Fibonacci sequence based generative music programme
- data sent via osc to PD
visuals to be added later
*/
import oscP5.*;
import netP5.*;

OscP5 oscP5;
NetAddress myRemoteLocation;

int n, f;
int factor = 7; //how many tones in the scale
int x, y;

void setup(){
 size(400, 400);
 frameRate(1);
 background(255);
 oscP5 = new OscP5(this, 12000);
 myRemoteLocation = new NetAddress("127.0.0.1", 12000);
}

void draw(){

 int result = (fib(f+=1));
 if (result > factor){
   result = result%factor;
 }
 else{
   result = result;
 }
 
 print("framerate: ");
 print(frameRate); //frameRate decreases every frame??
 print(" scale degree: "); //multiplier value for pd patch
 println(result);
 sendResult(result);
}

int fib(int n){
 if (n<2){
   return(1);
 }
 else{
   return(fib(n-2)+fib(n-1));
 }
}

void sendResult(int result) {
 OscMessage myMessage = new OscMessage("/fibo");  
 myMessage.add(result);
 oscP5.send(myMessage, myRemoteLocation);
}

Re: Calculating Fibonacci Sequence - Very Slow
Reply #1 - Apr 3rd, 2010, 6:10am
 
er, just don't recalculate the new number from the beginning in every frame.

use two local variables that store the last two values. new value = sum of previous 2. old old value becomes old value. old value becomes new value. repeat. O(1) rather than O(n).
Re: Calculating Fibonacci Sequence - Very Slow
Reply #2 - Apr 3rd, 2010, 6:11am
 
Written in great haste: use millis() to get the time accurately.

Since your code just needs the next consecutive Fibonacci number, use something like this to generate the next item in the sequence iteratively rather than recursively starting from scratch every time. It's certainly less memory-intensive!

Code:
int f0 = 0;
int f1 = 1;
int f2 = 1;

int nextFib()
{
  int result = f2;
  f0 = f1;
  f1 = f2;
  f2 = f0 + f1;
  return result;
}

void setup()
{
 for (int i = 0; i < 20;  i++)
 {
     println(nextFib());
 }
}

Re: Calculating Fibonacci Sequence - Very Slow
Reply #3 - Apr 3rd, 2010, 6:35am
 
Thanks for the swift replies, will try out your solutions.
Re: Calculating Fibonacci Sequence - Very Slow
Reply #4 - Apr 3rd, 2010, 7:06am
 
That worked very quickly, thanks. With the benefit of hindsight, it all makes sense Smiley
Re: Calculating Fibonacci Sequence - Very Slow
Reply #5 - Apr 3rd, 2010, 8:43am
 
One last question, when the nextFib() value exceeds the maximum integer size, what's the best way of resetting the f() values so the sequence can start again?
Re: Calculating Fibonacci Sequence - Very Slow
Reply #6 - Apr 3rd, 2010, 12:51pm
 
Solved, apparently banging head against computer eventually works to get the mind working.
Re: Calculating Fibonacci Sequence - Very Slow
Reply #7 - Apr 4th, 2010, 4:47am
 
Quote:
Trying to generate a Fibonacci sequence in processing, but I'm having trouble calculating the values quick enough - obviously the numbers can get quite large quite fast by recursion.


No one has mentioned this so I will. Recursion is an extremely powerful technique but should be used with caution. When covering recursion the classic problem used to demonstrate when it can be used is the Factorial calculation. (The factorial of a positive integer is that number multiplied by every positive integer smaller than itself i.e. factorial 5 = 5 x 4 x 3 x 2 x 1

The classic problem to demonstrate when not to use recursion is the calculation of the Fibonacci sequence! The reason for this is not just the amount of memory used but the amount of duplicate calculations.

For instance the calculation of fib(7) would be

fib(7) = fib(6) + fib(5)
Calculating the first part:   fib(6) + fib(5)
the call to fib(6) would call fib(5) and fib(4)
the call to fib(5) would call fib(4) and fib(3)
the call to fib(4) would call fib(3) and fib(2)
etc.
Calculating the second part:  fib(6) + fib(5)
the call to fib(5) would call fib(4) and fib(3)
the call to fib(4) would call fib(3) and fib(2)
etc.
Notice the multiple calls to fib(4) and fib(3) this only gets worse with larger numbers.
In fact the calculation is of order O(en) i.e. exponential.

There are always iterative alternatives to recursion and they are shown in this thread but sometimes the easiest solution can be a simple lookup table.

The following code uses a lookup table and displays the next Fibonacci number in the sequence every second reseting when they get to big.

Hope this is of interest.

Code:

int[] fibs;
final int FIBLIMIT = 47; // 93;
int nextFib = 1;
long etime;
long ftime = 1000;

int nextFib(){
 if(nextFib >= FIBLIMIT)
   nextFib = 1;
 return fibs[nextFib++];
}

void makeFibs(){
 fibs = new int[FIBLIMIT];
 fibs[1] = fibs[2] = 1;
 for(int i = 3; i < FIBLIMIT; i++){
   fibs[i] = fibs[i-1] + fibs[i-2];
  }
 nextFib = 1;
}

void setup(){
 makeFibs();
 etime = millis();

}

void draw(){
 if(millis() - etime > ftime){
   println(""+nextFib());
   etime = millis();
 }
}

Page Index Toggle Pages: 1