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:
01.def leibniz_pi_1(num_termos):
02.    """ Calcula valor de pi segundo fórmula de Leibniz.
03.    """
04.    conta = 0
05.    acum = 0.0
06.    den = 1
07.    while conta < num_termos:
08.        acum = acum + (1.0/den) * (-1)**conta
09.        den = den +2
10.        conta = conta + 1
11.    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.
01.def leibniz_pi_2(num_termos):
02.    """ Calcula valor de pi segundo fórmula de Leibniz.
03.    """
04.    acum = 0.0
05.    den = 1
06.    for i in range(num_termos):
07.        acum = acum + (1.0/den) * (-1)**i
08.        den = den +2
09.    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:
1.def leibniz_pi_3(num_termos):
2.    """ Calcula valor de pi segundo fórmula de Leibniz.
3.    """
4.    acum = 0.0
5.    for i in range(num_termos):
6.        acum = acum + ((-1)**i) * (1.0/(2 * i + 1)) 
7.    return 4 * acum

Passemos agora para o caso da aproximação pela fórmula de Wallis:
01.def wallis_1(num_fact):
02.    """
03.    Calcula o valor de pi usando a fórmula de Wallis.
04.    """
05.    acum = 1.0
06.    for i in range(2, num_fact,2):
07.        esquerda = i / float((i-1))
08.        direita = i /float((i+1))
09.        acum = acum * esquerda * direita
10.    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:
01.def wallis_2(num_fact):
02.    """
03.    Calcula o valor de pi usando a fórmula de Wallis.
04.    """
05.    acum = 1.0
06.    for i in range(1, num_fact/2):
07.        factor = float((2 * i) ** 2) / ((2 * i) ** 2 - 1)
08.        acum = acum * factor
09.    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