Finding the closest fibonacci numbers

user852689 picture user852689 · Oct 21, 2011 · Viewed 9.9k times · Source

I am trying to solve a bigger problem, and I think that an important part of the program is spent on inefficient computations.

I need to compute for a given number N, the interval [P, Q], where P is the biggest fibonacci number that is <= to N, and Q is the smallest fibonacci number that is >= to N.

Currently, I am using a map to record the value of the fibonacci numbers. A query normally involves searching all the fibonacci numbers up to N, and it is not very time efficient, as it involves a big number of comparisons.

This type of queries will occur quite often in my program, and I am interested in ways that I could improve the lookup, preferably with sub-linear complexity.

Answer

PengOne picture PengOne · Oct 21, 2011

The Fibonacci numbers are given by Binet's formula

F(n) = ( phi^n - (1-phi)^n ) / \sqrt{5}

where phi is the golden ratio,

phi = (1 + \sqrt{5}) / 2. 

This can be implemented straightforwardly (Python example):

<<fibonacci_binet.py>>=
phi = (1 + 5**0.5) / 2

def fib(n):
    return int(round((phi**n - (1-phi)**n) / 5**0.5))

Because of floating-point rounding errors, this will however only give the right result for n < 70.

Binet's formula can be inverted by ignoring the (1-phi)^n term, which disappears for large n. We can therefore define the inverse Fibonacci function that, when given F(n), returns n (ignoring that F(1) = F(2)):

<<fibonacci_binet.py>>=
from math import log

def fibinv(f):
    if f < 2:
        return f
    return int(round(log(f * 5**0.5) / log(phi)))

Here rounding is used to our advantage: it removes the error introduced by our modification to Binet's formula. The function will in fact return the right answer when given any Fibonacci number that can be stored as an exact integer in the computer's memory. On the other hand, it does not verify that the given number actually is a Fibonacci number; inputting a large Fibonacci number or any number close to it will give the same result. Therefore you can use this idea to find the Fibonacci number closest to a given number.

The idea, then is to apply the inverse Fibonacci map to find N and M, the two closest Fibonacci numbers on either side, then use the direct Fibonacci map to compute P = F(N) and Q = F(M). This involves more computation, but less searching.