É 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


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

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).


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
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.