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+×/


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)

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)


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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.