/* Programa raizes_tangente.c Assunto: Estudo das raizes de uma função definida no programa. Condicionantes: Programa sem erros, ver raizes012.c com mudança de variável Para compilar gcc -Wall -oprog raizes_tangente.c cria o executável prog que você pode rodar na linha de comandos em Linux. Descrição: Varre um intervalo com uma malha dada procurando quando f troca de sinal. Lendo os comentários você pode alterar o programa com segurança Altere (0) logo abaixo para refletir a posição das bibliotecas na sua árvore de diretórios. Palavras-chave: troca de sinal, raiz, varredura por Tarcisio Praciano Pereira - 10 lições para aprender C Sobral, Agosto de 2003 - UVA */ define limpa_janela() { system("clear"); } define entrada_float(msg, x) { printf("%s %f ",msg, x); scanf("%f", x); return(x); } define apeteco2() { local temporario; printf("%s","================================================= "); printf("%c%c%c%c%c\n",7,7,7,7,7); printf(" Aperte para continuar "); scanf("%f", temporario); return temporario; } /* há várias equações, para escolher uma, apague o comentário */ define f(x) { /* return(-(x+3)*(x+3)*(x-2)*(x+2) ); /* (50) */ /* return( x*x*x*x*x + x*x*x*x + x*x*x + x*x + x + 1); /* (50)*/ /* return(x*x); /* (50) escolha somente um return() */ /* return(x); /* (50) */ /* return( x*x*x*x*x - 4*x*x*x + x*x + 0.2*sin(19*x) - 0.10782); /* função com vários gogos...8?*/ return( x*x*x*x*x - 4*x*x*x + x*x + 0.2*sin(19*x) ); /* função com vários gogos...*/ } /* reta tangente y = f(a) + df(a)(x - a) */ /* zero da reta tangente x0 = a - f(a)/df(a) */ define raiz_tangente(a, b) { local epsilon=(b-a)/1000; /* precisão para o cálculo da raíz */ local M = (f(b)-f(a))/(b-a); /* (61) memoriza crescimento em [a,b] */ local x=a, m = (f(x+epsilon) - f(x))/epsilon; /* deriv. aproximada */ if (m*M < 0) while (m*M < 0) /* (62) pode ser ponto extremo com m = 0 */ { x = x + 20*epsilon; /* corre um pouco */ m = (f(x+epsilon) - f(x))/epsilon; x = x - f(x)/m; } else x = x - f(x)/m; /* raiz da tangente com der. aproximada m */ return(x); } define main() { local a=-5,b=5,delta=0.1; /* (10) valores default */ local epsilon=0.1, raiz; local teste=0; printf("Forneça-me o intervalo [a,b] para busca de raizes: \n"); a = entrada_float("a = ", a); b = entrada_float("b = ", b); printf("Forneça-me o passo delta da malha para a busca:\n"); printf("Sugestão 0.01 < delta < 0.5 \n"); delta = entrada_float("delta = ", delta); printf("Forneça-me o erro epsilon (módulo máximo) :\n"); printf("Sugestão 0.01 < epsilon < 0.5 \n"); epsilon = entrada_float("epsilon = ", epsilon); printf("Sua busca de raízes no intervalo [%f , %f] \n ",a,b); printf("Precisão da malha: %f \n ", delta); printf("Erro (módulo máximo): %f \n ", epsilon); apeteco2(); while( a <= b) { print a; if ( f(a)*f(a+delta)<=0 ) { if ( f(a) == 0 ) { printf("Uma raíz exata %f \n", a); a = a + delta; /* salto extra teste = teste + 1; /* conta raízes } else if ( f(a+delta) == 0 ) { printf("Uma raíz exata %f \n", a+delta); a = a + delta; /* salto extra teste = teste + 1; /* conta raízes } else { printf("Troca de sinal da função no intervalo "); printf("[ %f , %f] \n", a, a+delta); raiz = raiz_tangente(a,a+delta); printf("Raiz p/ método da tangente x = %f \n", raiz); printf("Valor de f na raíz aprox f(%f)=%f\n",raiz,f(raiz)); a = a + delta; /* salto extra */ teste = teste + 1; /* conta raízes */ } } a = a + delta; } if (!teste) { printf("Nenhuma raíz foi encontrada no intervalo dado !\n"); printf("Rode, novamente, o programa, com passo mais fino...\n"); } if (teste == 1) printf("Achei uma raíz \n"); else printf("Achei %d intervalos onde há raíz \n", teste); return(0); } /* Comentários: (10) Os dados do programa podem ser aceitos apenas dando enter quando for feita pergunta sobre valores a fornecer. Rode o programa apenas dando enter na primeira vez. (30) Há dois testes - troca de sinal e módulo máximo experimente apagar o módulo máximo, deixando apenas se ( (f(a)*f(a+delta)<=0) ) copie o texto acima e coloque em lugar de se() em (30), mas não apague porque você vai precisar deste programa ainda. Torne um comentário aquilo que você apagaria usando o símbolo ## (40) teste = 0 evita que seja escrita a mensagem informando que nenhuma raiz foi encontrada. (50) em uma função somente um return() deve ser executado. em f() há vários, todos desligados, menos um que é o que está em vigor. Troque pela equação desejada ou escolha outra equação. (60) No módulo raiz_tangente (61) M é o coeficiente angular da reta secante em (a,f(a)) (b,f(b)) para memorizar o crescimento global de f no intervalo de troca de sinal (62) A função pode ter muitos gogos no intervalo [a,b], oscilando antes de chegar no zero procurado. Se m*M for negativo ou zero pego o próximo ponto na malha fina e volto a testar até que m*M seja positvo - m tem o mesmo sinal de M */