Progressões Aritméticas e Geométricas
Objetivos de Aprendizagem
- Reconhecer uma progressão aritmética ou geométrica por uma diferença constante ou uma razão constante, e escrever o seu -ésimo termo.
- Deduzir e usar as formas fechadas da soma dos primeiros termos de cada uma, incluindo o caso especial e a contagem correta de termos.
- Decidir o comportamento de a longo prazo para toda razão real , e ligá-lo à convergência de uma sequência.
- Traduzir laços em somas: laços aninhados dão somas aritméticas, divisão pela metade e dobramento dão somas geométricas.
- Usar uma soma geométrica para explicar o custo de um array que dobra de tamanho e do crescimento composto, e contrastá-los com os equivalentes aritméticos.
Contexto e Motivação
Entre todas as sequências, duas famílias têm formas fechadas simples o bastante para serem tratadas exatamente e comuns o bastante para aparecer em quase toda análise de custo. Em uma progressão aritmética, cada termo difere do anterior por uma quantidade fixa . Em uma progressão geométrica, cada termo é um múltiplo fixo do anterior. A primeira descreve crescimento linear, a segunda crescimento exponencial, e o contraste entre elas é o contraste entre um laço que faz um pouco mais de trabalho a cada passada e um processo que multiplica o próprio tamanho.
Na lição anterior, sequences-and-convergence, você viu o que significa uma sequência se estabilizar. Uma progressão é o lugar mais fácil para praticar essa definição, já que a resposta é conhecida em forma fechada. As somas de progressões também são o ponto em que a sequência vira uma nova sequência, a das somas parciais, a ideia sobre a qual a próxima lição, infinite-series-and-partial-sums, se constrói. A lição de estruturas de dados dynamic-arrays-and-amortized-resizing argumenta que dobrar um array cheio mantém as inserções baratas em média e que somar uma quantidade fixa não mantém. Esta lição fornece a aritmética por trás das duas afirmações e as confere com uma contagem de verdade.
Teoria Central
Progressões aritméticas
Uma sequência com para todo é uma progressão aritmética de primeiro termo e razão (diferença) . Seus termos são
Sua soma pode ser obtida escrevendo a soma duas vezes, uma na ordem direta e outra na inversa, e somando coluna por coluna: toda coluna soma , e há colunas, então . Logo
A mesma fórmula pode ser provada por indução, como em mathematical-induction. O caso especial , dá . Para , os termos crescem linearmente em e as somas quadraticamente. Se , a sequência diverge (cresce sem limite, para cima ou para baixo), e se ela é constante.
Progressões geométricas
Uma sequência com é uma progressão geométrica de razão :
Para a soma, subtraia de . Todos os termos se cancelam, exceto o primeiro e o último, restando , e portanto
Essa fórmula divide por , então não vale para . Nesse caso todo termo é e . Quando a soma começa no expoente , como em , há termos e a fórmula fica . Contar os termos errado é o erro mais comum ao aplicá-la.
O que faz
O comportamento da sequência é a história toda da convergência das progressões geométricas:
- Se , então .
- Se , a sequência é constante igual a .
- Se , ela alterna entre e e diverge.
- Se , então . Se , os termos alternam de sinal e seu tamanho cresce sem limite, então diverge.
Para ver o primeiro caso, note que é imediato; para , escreva com . A desigualdade de Bernoulli dá , logo , e o teorema do confronto conclui. Em consequência, uma progressão geométrica converge exatamente quando (para ) ou (para ), desde que . E quando , a forma fechada mostra as somas parciais se estabilizando em , já que (a próxima lição transforma isso em um teorema sobre séries infinitas).
Laços, metades e dobros
Contar as iterações de um programa muitas vezes significa somar uma progressão. Um laço interno cuja cota cresce de um em um a cada passada externa dá uma soma aritmética, portanto no total. Uma grandeza dividida pela metade a cada passo, como no laço while n > 1: n //= 2, executa vezes, e em uma recursão que faz trabalho proporcional ao tamanho da entrada e depois recorre sobre a metade dela, as quantidades sucessivas formam uma progressão geométrica. Em uma soma geométrica com , o último termo domina: é menor que o dobro do último termo . É esse fato que torna o dobramento barato.
Exemplos Resolvidos
Exemplo 1: somas aritméticas vindas de laços
O laço for i in range(n): for j in range(i): count += 1 executa o corpo interno vezes. Rodá-lo dá para , para e para , coincidindo com a fórmula em todos os casos. É cerca de metade de , mas ainda quadrático.
Agora inverta a pergunta. Para a progressão (ou seja, , ), ache o menor com . Aqui , então precisamos de . A raiz positiva é . Confira os vizinhos: e . A resposta é , cujo último termo é .
Exemplo 2: somas geométricas e a contagem de termos
Para com termos, , :
Para com termos, . Somar os dez termos diretamente dá o mesmo número. A soma vale , o maior número que cabe em dez bits, já que cada bit ligado contribui com uma potência de dois. Os expoentes de a dão termos, não .
Exemplo 3: contando as cópias de um array que dobra
Cada inserção em um array cheio copia todos os elementos guardados para um array maior. O script abaixo conta apenas essas cópias, partindo da capacidade , para duas regras de crescimento: dobrar a capacidade e somar posições.
plaintextdef count_copies(n, grow): capacity, length, copies = 1, 0, 0 for _ in range(n): if length == capacity: # cheio: aloca um array maior e copia copies += length capacity = grow(capacity) length += 1 # a própria inserção (uma escrita) return copies for n in (10, 1_000, 10_000, 100_000, 1_000_000): dbl = count_copies(n, lambda c: 2 * c) inc = count_copies(n, lambda c: c + 16) print(f"{n:>9} doubling: {dbl:>9} ({dbl / n:.2f} per append) +16: {inc:>12} ({inc / n:.1f} per append)")
Sua saída:
text10 doubling: 15 (1.50 per append) +16: 1 (0.1 per append) 1000 doubling: 1023 (1.02 per append) +16: 31311 (31.3 per append) 10000 doubling: 16383 (1.64 per append) +16: 3120625 (312.1 per append) 100000 doubling: 131071 (1.31 per append) +16: 312456250 (3124.6 per append) 1000000 doubling: 1048575 (1.05 per append) +16: 31249562500 (31249.6 per append)
Dobrando. As realocações acontecem quando o comprimento é , então as cópias formam a soma geométrica , em que é a capacidade final, a menor potência de dois que é pelo menos . Para isso é , exatamente a contagem. Como , as cópias ficam sempre abaixo de , que é a cota usada em dynamic-arrays-and-amortized-resizing. A razão por inserção não é constante: vale em e em , porque o array dobrou para a capacidade na inserção , e as cópias até ali estão espalhadas por apenas inserções. Ela fica abaixo de o tempo todo.
Somando 16. As realocações acontecem nos comprimentos , uma progressão aritmética com . Com , as cópias somam . Para , e o total é , como contado. O custo por inserção cresce como , então só piora conforme cresce.
Isso compara apenas cópias. Dobrar cobra em memória: logo depois de uma realocação até metade do array fica sem uso, enquanto somar desperdiça no máximo posições. E o fator não é especial. Crescer a capacidade por qualquer fator fixo mantém as cópias por inserção limitadas por cerca de , de modo que o fator (arredondado para cima) mede por inserção em e o fator mede . Um fator menor troca menos posições ociosas por mais cópias.
Exemplo 4: crescimento composto contra crescimento simples
Considere uma conta com saldo , taxa anual fixa de e capitalização anual. Juros simples somam por ano, uma progressão aritmética: , que vale após anos. Juros compostos multiplicam por , uma progressão geométrica: vale após ano, após e após . O saldo dobra quando , em anos (a regra prática chega perto).
Depósitos regulares formam uma soma geométrica. Depositar no fim de cada mês durante meses, à taxa mensal , dá , enquanto os depósitos em si somam . Aplicar os depósitos mês a mês em um laço reproduz .
Equívocos Comuns e Armadilhas
- Erro de um na contagem de termos. A soma tem termos, e usar no expoente da fórmula dá a resposta errada. Escreva o primeiro e o último expoente, conte e só então substitua.
- Aplicar a fórmula geométrica em . Ela divide por zero. A soma é , e esse caso importa porque um laço de razão exatamente é só um laço.
- "A soma de uma progressão aritmética é linear." Para , os termos são lineares em e a soma é quadrática. Um laço aninhado com cota que cresce com o contador externo é , mesmo que a contagem interna seja "apenas" .
- "Uma progressão geométrica com é dominada pelos primeiros termos." Para o último termo domina, e a soma é um múltiplo limitado dele. Para o primeiro termo domina. Por isso os custos de cópia de um array que dobra somam um pequeno múltiplo de .
- "Amortizado O(1) significa que cada inserção é barata." No Exemplo 3, a inserção no comprimento copia esse tanto de elementos de uma vez. A afirmação trata da média sobre muitas inserções, não de uma inserção qualquer.
- "Uma razão faz os termos tenderem a ." Os termos alternam de sinal com tamanho crescente, então a sequência não tem limite algum, finito ou infinito.
Resumo
Uma progressão aritmética soma uma diferença fixa: e , então, para , os termos crescem linearmente e as somas quadraticamente. Uma progressão geométrica multiplica por uma razão fixa: e para , com em . A sequência tende a exatamente quando , o que decide quando uma progressão geométrica converge. Contar os termos com cuidado importa, porque o mesmo padrão dá ou termos conforme onde o expoente começa. Na computação, laços aninhados produzem somas aritméticas, dividir pela metade produz passos, e dobrar produz uma soma geométrica dominada pelo último termo, e por isso um array que dobra copia menos de elementos em inserções, enquanto um incremento fixo de copia cerca de . O crescimento composto é a mesma estrutura geométrica com dinheiro no lugar de memória. A próxima lição, infinite-series-and-partial-sums, pergunta o que acontece com essas somas quando o número de termos pode crescer para sempre.