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.