É possível encontrar o enésimo termo de uma sequência de Fibonacci usando um loop for definitivo?

7

Estou usando o livro Introdução à Ciência da Computação, de John Zelle, e no final do Capítulo 3 (Computando com números), me pedem para encontrar o enésimo termo de uma sequência de Fibonacci, presumivelmente usando um loop for definitivo, como nenhuma outra decisão estrutura foi introduzida ainda.

Isso é possível? Eu tentei tudo o que pude pensar.

** Eu sei como resolvê-lo usando declarações if e tal. Mas o livro ainda não abordou estruturas de decisão, mas pede-me para encontrar o enésimo termo (fornecido pelo usuário). Portanto, só posso presumir saber como fazer isso usando loops "for", pois isso é tudo o que foi abordado até agora

qzxt
fonte
11
O que significa "definitivo para loop"?
9788 Keith Thompson
Basicamente, um loop contado. Por exemplo, eu tomo o enésimo termo como entrada e dizer for i in range (entrada):
qzxt
Eu poderia remover ifinstruções movendo as expressões condicionais para loops, mas isso seria apenas um truque completamente inútil, IMHO.
toniedzwiedz
Então, eu não sou louco, então, e realmente não há distância para fazer isso sem condicionais?
qzxt
@qzxt não, se você quiser pegar entradas inválidas, não.
toniedzwiedz

Respostas:

11

Se for apenas o terceiro capítulo, duvido que os autores tenham abordado a programação dinâmica, mas ilustrarei o que está acontecendo quando um loop for é usado para calcular o nº Número de Fibonacci, Fn.

Lembre-se da definição,

Fn={0 0n=0 01 1n=1 1Fn-1 1+Fn-2de outra forma

Poderíamos computar ingenuamente isso usando uma função recursiva definida em Python como,

def fib(n):
    if n < 2:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

No entanto, recalculando o mesmo subproblema várias vezes, essa função exige tempo exponencial para a computação (ilustrada abaixo)! fibtree

Há uma correção, no entanto. Podemos usar a programação dinâmica para fazer recursões "mais inteligentes" e manter os resultados anteriores por perto. Dessa forma, não precisamos recalcularFEu. Nossa chamada de função "árvore" entrará em colapso em uma lista e calcularáFn do "de baixo para cima". fib2

def fib2(n):
    if n < 2:
        return n
    else:
        if not results[n]:
            results[n] = fib2(n - 1) + fib2(n - 2)
        return results[n]

Agora nós temos nossa O(n) algoritmo de tempo para calcular Fn, mas se você perceber, exigimos O(n) espaço adicional (um ponto na matriz para cada FEu) Isso pode ser reduzido paraO(1 1) espaço adicional porque cada FEu requer apenas dois outros números de fibonacci, a saber FEu-1 1 e FEu-2.

def fib3(n):
    if n < 2:
        return n
    f_0 = 0
    f_1 = 1
    f_n = 0
    for _ in range(n - 1):
        f_n = f_0 + f_1
        f_0 = f_1
        f_1 = f_n


    return f_n
Nicholas Mancuso
fonte
2
Uau, ótima resposta! Observe que é fácil colocar isso em um formato compatível com recursão primitiva - ou seja, contagem decrescente em definições comuns - usandon-Eudentro do loop (de contagem regressiva).
Raphael
10

Se você precisar usar apenas um loop for que itera até encontrar o n-ésimo número de Fibonacci, use algo como isto:

int fib(int n)
{
    int p = 0;
    int c = 1;
    int r = 0; // The result is initialized to 0 (undefined). 
    for (int i = 0; i < n; i++)
    {
        r = p + c; // Produce next number in the sequence.
        p = c;     // Save previous number.
        c = r;     // Save current number.
    }

    return r;
}

NOTA

Na solução acima, presumo que a sequência de Fibonacci seja 1 1 2 3 5 8 13 ... e que n tenha o intervalo 1, 2, 3, ... Visto que nessas suposições, não há número de Fibonacci para n <1 , a função retorna um 0 para n <1 para indicar que o parâmetro de entrada está fora da faixa (consulte as sugestões de Tom nos comentários abaixo).

Giorgio
fonte
A saída para 0 deve ser 0, caso contrário, uma resposta boa, simples e concisa.
precisa saber é o seguinte
Depende de como você conta, na verdade, fib deve ser indefinido para n <1. Ou você quer dizer que 0 representa indefinido e, portanto, fib (n) deve retornar 0 para todos os n <1?
Giorgio
Isso é verdade, depende. Se incluirmos 0, a saída deverá ser 0. Se a excluirmos, a função retornará um valor especial para indicar entrada inválida, o que também deve ser feito para números negativos ... mas o OP não aceita expressões condicionais, muito menos jogando exceções, então acho que está tudo bem do jeito que está.
toniedzwiedz
2
@Giorgio Matematicamente, a sequência de Fibonacci está perfeitamente bem definida para n<0 0; não há nada que impeça você de executar a sequência para trás , invertendofn+1 1=fn+fn-1 1 para obter fn-1 1=fn+1 1-fn - ou, definindo gn=f-n, gn+1 1=gn-1 1-gn.
Steven Stadnicki 6/03/2013