quinta-feira, 13 de outubro de 2011

Calcular o valor aproximado de PI

Pi é um número irracional e, por isso, o melhor a que podemos aspirar é calcular o seu valor aproximado. Ao longo dos séculos foram aparecendo várias formas de o fazer. Uma delas foi proposta por Leibniz:



Outra por Wallis:



Se as fórmulas são distintas do ponto de vista informático são muito semelhantes, uma vez que remetem para um mesmo padrão de programação, baseado no recurso a um ciclo, uma variável de contagem e outra variável de acumulação.

A ideia da solução consiste em ir acrescentando ao longo do ciclo um termo (caso de Leibniz) ou um factor (caso de Wallis) ao resultado parcial.

Comecemos com o caso da abordagem de Leibniz:

def leibniz_pi_1(num_termos):
""" Calcula valor de pi segundo fórmula de Leibniz.
"""
conta = 0
acum = 0.0
den = 1
while conta < num_termos:
acum = acum + (1.0/den) * (-1)**conta
den = den +2
conta = conta + 1
return 4 * acum

Nesta solução é claro que conta faz o papel de contador, e acum o de acumulador. Notar o modo como geramos o termo de ordem i, com o auxílio da variável den. Esta solução pode ser simplificada se tornarmos o contador implícito recorrendo a um ciclo for.

def leibniz_pi_2(num_termos):
""" Calcula valor de pi segundo fórmula de Leibniz.
"""
acum = 0.0
den = 1
for i in range(num_termos):
acum = acum + (1.0/den) * (-1)**i
den = den +2
return 4 * acum

Mas a fórmula de Leibniz também pode ser apresentada na sua forma compacta:



Se a usarmos directamente chegamos ao programa:

def leibniz_pi_3(num_termos):
""" Calcula valor de pi segundo fórmula de Leibniz.
"""
acum = 0.0
for i in range(num_termos):
acum = acum + ((-1)**i) * (1.0/(2 * i + 1))
return 4 * acum

Passemos agora para o caso da aproximação pela fórmula de Wallis:

def wallis_1(num_fact):
"""
Calcula o valor de pi usando a fórmula de Wallis.
"""
acum = 1.0
for i in range(2, num_fact,2):
esquerda = i / float((i-1))
direita = i /float((i+1))
acum = acum * esquerda * direita
return 2 * acum

Este modo de resolver já tem o contador implícito e baseia-se no facto de podermos agrupar os factores aos pares, pois.



Assim, em cada passagem pelo ciclo, calculamos dois factores.

Mas podemos também fazer uso da forma compacta:



Daqui decorre a nova versão do programa:

def wallis_2(num_fact):
"""
Calcula o valor de pi usando a fórmula de Wallis.
"""
acum = 1.0
for i in range(1, num_fact/2):
factor = float((2 * i) ** 2) / ((2 * i) ** 2 - 1)
acum = acum * factor
return 2 * acum

Se compararmos esta versão com a última versão de Leibniz, fica claro o que queremos dizer quando falamos de semelhanças.

Sem comentários:

Enviar um comentário