O valor aproximado de
pode ser calculado da seguinte forma:
PASSO 1: Calcula-se o valor da série com n termos:
PASSO 2: Calcula-se o valor aproximado de
pela expressão:
Desenvolva um programa que peça para o usuário informar a quantidade n de termos da série, calcule e exiba o valor aproximado de
com 14 casas decimais.
Obs. 1: Para aumentar a exatidão no cálculo do valor do
, utilize o tipo de dados double ao invés do float. A máscara de formatação para o double é olf.
Obs. 2: Para calcular a raiz cúbica, utilize a função cbrt () disponível na biblioteca math.h.
Valor de referência (14 casas decimais):
PASSO 1: Calcula-se o valor da série com n termos:
Valor de referência (14 casas decimais):
Passo 1
O enunciado pede que eu escreva um programa que leia a quantidade
de termos de uma série, calcule o valor aproximado de
seguindo dois passos e exiba o resultado com 14 casas decimais. As informações fornecidas são:
Requisitos do programa (dados no enunciado): usar o tipo de dados
, usar a função
da biblioteca
para a raiz cúbica e imprimir com 14 casas decimais (máscara
). Valor de referência de
com 14 casas:
.
Passo 2
Um ponto importante de entendimento (didática): a identidade conhecida que liga uma série de inversos de cubos de números ímpares a
é
Ou seja, a série que converge para
é a série alternada
Se usarmos essa série alternada com
termos e calcularmos
por
, a aproximação converge para
. Se usássemos a série com todos os sinais positivos, a relação com
não seria a acima e a fórmula
não valeria. Portanto, para que o programa produza uma boa aproximação de
conforme o enunciado, devemos somar a versão alternada dos termos ímpares ao cubo.
Breve comentário sobre por que essa identidade existe (sem prova completa): ela pode ser obtida a partir da expansão em série de Taylor (ou de Fourier) da função
e manipulações integrais/termwise que levam a somas de potências ímpares; a identidade é clássica e usada para obter
a partir de séries. Aqui vamos aceitar a identidade como base do método e mostrá-la numericamente no programa.
Passo 3
Como implementar o cálculo (passo a passo prático e didático):
- Representação da série finita com
termos: vamos somar os termos
Cada termo é calculado assim:
- calcular o índice ímpar
; - calcular
(usando cast para ); - calcular o inverso
; - aplicar o sinal
: se for par, somamos; se for ímpar, subtraímos.
-
Acumular a soma em uma variável do tipo
para aproveitar a precisão. -
Após calcular
, calcular a aproximação de por
Observações de implementação:
- Não usar
desnecessariamente; é mais eficiente fazer com convertido para . - Ler
com e verificar se . - Imprimir com
.
Passo 4
Estimativa de quantos termos são necessários para atingir 14 casas decimais:
A série alternada tem termos monoticamente decrescentes em magnitude, logo o erro absoluto ao truncar a
-ésima parcela é menor que o valor do próximo termo (Critério do resto da série alternada):
Se quisermos erro em
menor que
, precisamos de
Portanto
da ordem de
(aprox.
) é suficiente para fazer o erro em
menor que
. A sensibilidade da transformação
é da mesma ordem (fator aproximadamente
), então esse
também dá aproximadamente 14 dígitos corretos em
. Conclusão prática: escolher
na casa de
garante 14 casas decimais estáveis; para valores menores de
ainda obtém-se aproximações, mas com menos casas corretas.
Passo 5
Cuidados numéricos e boas práticas:
- Usar
para acumular . - Somar termos em ordem crescente de magnitude tende a reduzir erro de arredondamento; aqui a sequência dos termos já diminui com
crescente, então somar do termo até é aceitável. Se for muito grande, pode-se considerar soma em dupla precisão (não padrão em C) ou soma em ordem crescente (já é o caso). - Evitar convertendo repetidamente usando
; calcular como inteiro e fazer .
Passo 6
Programa em C completo (segue o código que implementa o algoritmo descrito). Esse programa lê um inteiro
, calcula
como série alternada, calcula
usando
e imprime com 14 casas decimais.
#include <stdio.h>
#include <math.h>
int main(void) {
int n;
if (scanf("%d", &n) != 1) return 0;
if (n <= 0) {
printf("0.00000000000000\n");
return 0;
}
double S = 0.0;
for (int k = 0; k < n; ++k) {
int m = 2*k + 1; /* ímpar m = 1,3,5,... */
double dm = (double)m;
double term = 1.0 / (dm * dm * dm); /* 1 / m^3 */
if (k % 2 == 1) {
term = -term; /* alterna o sinal: -, +, -, + ... */
}
S += term;
}
double pi_approx = cbrt(32.0 * S);
printf("%.14lf\n", pi_approx);
return 0;
}
Resposta
#include <stdio.h>
#include <math.h>
int main(void) {
int n;
if (scanf("%d", &n) != 1) return 0;
if (n <= 0) {
printf("0.00000000000000\n");
return 0;
}
double S = 0.0;
for (int k = 0; k < n; ++k) {
int m = 2*k + 1;
double dm = (double)m;
double term = 1.0 / (dm * dm * dm);
if (k % 2 == 1) term = -term;
S += term;
}
double pi_approx = cbrt(32.0 * S);
printf("%.14lf\n", pi_approx);
return 0;
}