Ir ao conteúdo

Algoritmo para calcular cosseno


Giiovanna

Posts recomendados

Postado

Olá,

Preciso fazer um programa que calcule o cosseno utilizando a Série de Taylor. Para quem não conhece, é o somatório, para k tendendo a infinito de

(-1)^k * x^2k / (2k)!

Esse k varia de 1 em 1.

Pois bem. Fazendo o programa, resolvi fazer uma função que calculasse o fatorial, que ficou da seguinte maneira:

int fat (int k) {

int fatorial=1, i=1;

while(i<=k) {fatorial=fatorial*i; i++}

return (fatorial);

}

Que funciona perfeitamente.

Para calcular o cosseno pela série de taylor, utilizei o seguinte método:

int k=0;

double termo, cosseno;

cosseno=0;

termo=pow(-1,k)*pow(x,2*k)/fat(2*k);

while (fabs(termo) <= 0.0001) {

termo=pow(-1,k)*pow(x,2*k)/fat(2*k);

cosseno=cosseno+termo;

k++;

}

Porém, quando tento calcular cosseno de x radianos, a função não vai. O programa fica parado, sem fazer nada.

Tentei utilizar outro método sem a função fatorial que ficou da seguinte maneira:

.

.

.

cosseno=1;

termo=x*x

k=1;

m=1;

denominador=1;

while (fabs(termo) <= 0.0001) {

sinal=pow(-1,m);

m++; /* Contador */

denominador=denominador*k*(k+1); /* Calcula o fatorial utilizando o fatorial anterior */

k=k+2; /* Some 2 ao contador dos fatoriais */

termo=sinal*pow(x,2*m)/denominador;

cosseno=cosseno+termo

}

Dessa segunda forma funciona. Porém, quando coloco valores de cosseno maiores que 35, o cosseno começa a passar de 1.

Alguém tem ideia por que a função com o fatorial (1ª função) não está funcionando? E a segunda, por que trava para valores de x maiores que 35 radianos?

Agradeço, peço desculpas pela dúvida longa, mas tentei especificar da melhor maneira possível

Postado

Olliver, foi erro de digitação meu aqui na hora, desculpe. A função original possui o i++

Sabe qual pode ser o problema?

Agradeço por ter respondido.

Postado

Giiovanna,

Neste link abaixo, a partir da quinta mensagem, um problema semelhante (para cálculo do seno) é discutido e acho que pode te dar uma base:

Note que você não precisa criar uma função para o cálculo do fatorial e nem de potência explicitamente. Você pode ir multiplicando e acumulando os valores no próprio loop usado para calcular cada termo da série. Como ocorre no seu segundo método.

http://forum.clubedohardware.com.br/resolvido-problemas-logica/1041469?p=5574285#post5574285

No caso do problema acima, a precisão é fornecida pelo usuário. No seu caso, a precisão já foi definida em 0.0001.

[]'s

LNW

Postado

Olá LNW, obrigada pela resposta. Olhei os posts mas não achei nada que me ajudasse. Vou colocar agora o meu código completo, que calcula o cosseno pela série de taylor e utilizando a função cosseno:

Feito com o dev c++. Utilizei só os loops para "economizar", sem calcular fatoriais desnecessários.

A partir de 38 radianos, a fórmula começa a falhar.

Você acha que é por causa do estouro mesmo ou existe algum outro erro aparente? Tentei utilizar long para aumentar o armazenamento mas não funcionou.

O que eu poderia fazer?

Descobri que os fatoriais estão sendo calculados corretamente:

fatorial.png

mesmo assim, o cosseno continua incorreto. Algo não deve estar funcionando bem.

O 1 eu estou somando a parte e utilizando o termo geral somente para k >= 1. Poderia ser isso?

Postado

Giiovanna, ;)

A partir de 38 radianos, a fórmula começa a falhar.

Você acha que é por causa do estouro mesmo ou existe algum outro erro aparente? Tentei utilizar long para aumentar o armazenamento mas não funcionou.

O seu programa está funcionando. ;)

E sobre aquela discrepância ao entrar com o valor 38, sim, é por extrapolar o limite que um double comporta. Tanto que se você entrar com o valor 100, o seu cálculo retorna -1.#IND00, enquanto que a função retorna 0.862319.

38.0 em radianos é apenas um valor grande, mas a angulação é a mesma. Por exemplo, qual seria o cosseno de 360 e 1440 (em graus)? ;)

Então, você poderia diminuir qualquer valor de entrada que fosse maior ou igual ao valor de 2*pi.

No seu código, você incluiria (logo após os include's):

#define M_2PI		6.28318530717958647692

E logo após o scanf():

while (x >= M_2PI)
x -= M_2PI;

Outra sugestão agora para o seu código: aumente a precisão do termo testado para 0.000001.

Teste aí...

[]'s

LNW

Postado

Olá LNW. Havia pensado isso do 2pi mas não consegui fazer, mas agora você me deu a ideia, obrigada. Minha ideia foi substituir os angulos grandes por cossenos na primeira volta. Assim que arrumar o código, posto aqui os resultados.

Quanto à precisão, essa série faz parte de um exercício de programação de cálculo de integrais. O valor foi definido, então não posso mudar a priori.

Obrigada pela ajuda, volto a postar aqui os resultados.

Postado
Olá LNW, peguei a sua ideia e adaptei à minha, está funcionando perfeitamente.

Agradeço a ajuda e a atenção.

Muito obrigada :D

Que bom que tenha funcionado. ;)

E de nadinha, seja sempre bem-vinda. :):D

:wub:

LNW

  • 4 semanas depois...
  • Moderador
Postado

Caso o autor do tópico necessite, o mesmo será reaberto, para isso deverá entrar em contato com a moderação solicitando o desbloqueio.

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!