I know how to make the list of the Fibonacci numbers, but i don\'t know how can i test if a given number belongs to the fibonacci list - one way that comes in mind is genera
The general expression for a Fibonacci number is F(n) = [ [(1+sqrt(5))/2] sup n+1 - [(1-sqrt(5))/2] sup n+1 ]/ sqrt(5) ..... (*) The second exponential goes to zero for large n and carrying out the numerical operations we get F(n) = [ (1.618) sup n+1 ] / 2.236
If K is the number to be tested log(k*2.2336)/log(1.618) should be an integer!
Example for K equal to 13 my calculator gives the answer 7.00246 For K equal 14 the answer is 7.1564.
You can increase the confidence in the result by taking the closest integer to the answer and substitute in (*) to confirm that the result is K
How big are the numbers you're dealing with?
Could a lookup table work for you? (a precomputed list of numbers you can search in)
There's also a closed-form expression that I guess you could invert to get at the answer analytically (though I'm no mathematician, so I can't promise this suggestion makes sense)
If your numbers are of bounded size, than simply putting all fibonacci numbers below the upper bound into a hashtable and testing containment will do the trick. There are very few fibonacci numbers (for example, only 38 below 5mln), since they grow exponentially.
If your numbers are not of bounded size, then the suggested trick with square testing will almost surely be slower than generating the fibonacci sequence until the number is found or exceeded.
While several people point out the perfect-square solution, it involves squaring a Fibonacci number, frequently resulting in a massive product.
There are less than 80 Fibonacci numbers that can even be held in a standard 64-bit integer.
Here is my solution, which operates entirely smaller than the number to be tested.
(written in C#, using basic types like double
and long
. But the algorithm should work fine for bigger types.)
static bool IsFib(long T, out long idx)
{
double root5 = Math.Sqrt(5);
double phi = (1 + root5) / 2;
idx = (long)Math.Floor( Math.Log(T*root5) / Math.Log(phi) + 0.5 );
long u = (long)Math.Floor( Math.Pow(phi, idx)/root5 + 0.5);
return (u == T);
}
out
.
Parameter #2 is the "Index" into the Fibonacci sequence.
If the value to be tested, T
is a Fibonacci number, then idx
will be the 1-based index of that number in the Fibonacci sequence. (with one notable exception)
The Fibonacci sequence is 1 1 2 3 5 8 13
, etc.
3 is the 4th number in the sequence: IsFib(3, out idx);
will return true
and value 4
.
8 is the 6th number in the sequence: IsFib(8, out idx);
will return true
and value 6
.
13 is the 7th number; IsFib(13, out idx);
will return true
and value 7
.
The one exception is IsFib(1, out idx);
, which will return 2
, even though the value 1 appears at both index 1 and 2.
If IsFib
is passed a non-Fibonacci number, it will return false
, and the value of idx
will be the index of the biggest Fibonacci number less than T
.
16 is not a Fibonacci value.IsFib(16, out idx);
will return false
and value 7
.
You can use Binet's Formula to convert index 7 into Fibonacci value 13, which is the largest number less than 16.
From Wikipedia: http://en.wikipedia.org/wiki/Fibonacci_number
A positive integer z is a Fibonacci number if and only if one of 5z^2 + 4 or 5z^2 − 4 is a perfect square.
Re: Ahmad's code - a simpler approach with no recursion or pointers, fairly naive, but requires next to no computational power for anything short of really titanic numbers (roughly 2N additions to verify the Nth fib number, which on a modern machine will take milliseconds at worst)
// returns pos if it finds anything, 0 if it doesn't (C/C++ treats any value !=0 as true, so same end result)
int isFib (long n)
{
int pos = 2;
long last = 1;
long current = 1;
long temp;
while (current < n)
{
temp = last;
last = current;
current = current + temp;
pos++;
}
if (current == n)
return pos;
else
return 0;
}