Algoritmo eficiente para calcular o º número de Fibonacci

11

O º número de Fibonacci pode ser calculado em tempo linear usando o seguinte recorrência:n

def fib(n):
    i, j = 1, 1
    for k in {1...n-1}:
        i, j = j, i+j
    return i

O º número de Fibonacci também pode ser computada como . No entanto, isso tem problemas com problemas de arredondamento para relativamente pequeno . Provavelmente existem maneiras de contornar isso, mas eu prefiro não fazer isso.n[φn/5]n

Existe uma eficiente (logarítmica no valor ou melhor) algoritmo para calcular o º número de Fibonacci que não depende de aritmética de ponto flutuante? Suponha que operações inteiras ( , , , ) possam ser executadas em tempo constante.nn+×/

augurar
fonte
5
Como sugestão, o artigo da Wikipedia sobre números de Fibonacci possui muitos métodos.
Pseudônimo
cf. stackoverflow.com/questions/14661633/… e links nele e ao redor.
Will Ness

Respostas:

14

Você pode usar a alimentação de matriz e a identidade No seu modelo de computação, este é um algoritmo O ( log n ) se você usar quadrados repetidos para implementar a alimentação.

[1110]n=[Fn+1FnFnFn1].
O(logn)
Yuval Filmus
fonte
1
É um clássico.
Dfeuer
8
Você também pode usar essa identidade para derivar as recorrências e F 2 n = F 2 n + 2 F n - 1 F n . F2n1=Fn2+Fn12F2n=Fn2+2Fn1Fn
Augurar 25/01
4

Você pode ler este artigo matemático: Um algoritmo rápido para calcular grandes números de Fibonacci (Daisuke Takahashi): PDF .

Mais simples, implementei vários algoritmos de Fibonacci em C ++ (sem e com GMP) e Python. Fontes completas no Bitbucket. Na página principal, você também pode seguir os links para:

  • A documentação online em HTML do C ++.
  • Um pequeno documento matemático: números de Fibonacci - várias relações para implementar bons algoritmos

As fórmulas mais úteis são:

  • F2n=Fn+12Fn12=2FnFn1+Fn2
  • F2n+1=Fn+12+Fn2

Tenha cuidado com o algoritmo. Você não deve calcular o mesmo valor várias vezes. Um algoritmo recursivo simples (em Python):

def fibonacci_pair(n):
    """Return (F_{n-1}, F_n)"""
    if n != 0:
        f_k_1, f_k = fibonacci_pair(n//2)  # F_{k-1},F_k with k = n/2

        return ((f_k**2 + f_k_1**2,
                 ((f_k*f_k_1)*2) + f_k**2) if n & 1 == 0  # even
                else (((f_k*f_k_1)*2) + f_k**2,
                      (f_k + f_k_1)**2 + f_k**2))
    else:
        return (1, 0)

Sua complexidade é logarítmica (se as operações básicas estiverem em tempo constante): .O(logn)

Olivier Pirson
fonte
2
Bem-vindo à Ciência da Computação . Você poderia adicionar mais informações à sua resposta? No momento, nada mais são do que dois links. Portanto, sua resposta ficará sem sentido se esses links morrerem ou se os servidores em que estiverem instalados não estiverem disponíveis. Links para mais informações são bons, mas os links aqui são as únicas informações. Além disso, observe que a pergunta é muito definitivamente sobre algoritmos, não sobre implementações em C ++. As implementações tendem a obscurecer os algoritmos por trás dos detalhes específicos do idioma.
David Richerby
David, o primeiro link é um link para um artigo matemático. O título Um algoritmo rápido [...] responde à pergunta "Existe um algoritmo eficiente (logarítmico no valor n ou melhor)?" O segundo link é um link para minhas várias implementações, em C ++ e Python, e um pequeno documento matemático com várias fórmulas.
Olivier Pirson
2
Não, o título do artigo, que é a sua resposta, não responde nada. O texto do artigo, cuja resposta não contém quase nenhuma, parece que provavelmente responde à pergunta. Mas o Stack Exchange é um site de perguntas e respostas, não um farm de links. (E, não, eu não estou sugerindo que você copiar e colar o artigo em sua resposta Mas é necessário um resumo..)
David Richerby
Se você quiser um resumo, escreva-o!
Olivier Pirson
0

O(log2n)

Verifique o livro gratuito Matters Computational e o código pari / gp.

joro
fonte
5
Melhor resumir as ideias em vez de apenas postar links.
Augurar