Metodo Newton, Bisseccao e Secante; AJUDA

1. Metodo Newton, Bisseccao e Secante; AJUDA

Renan
hqmac

(usa Outra)

Enviado em 14/12/2015 - 10:29h

Olá pessoal,

sou totalmente novo nessa area de programação e virei a noite tentando fazer esse programa em C que é pra trabalho de faculdade pra amanhã. Mas acho que esta com alguns problemas que não sei resolver.

Quem puder ajudar serei muito grato.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int main () {
printf ("Programa para Estimar Raízes\n\n");

//Declaração de Variáveis
double a=0, b=0, t=0, erro,f=0,fd=0;
int i=0, potencia=0, cnt=0, opcao=0;
double coef[15]={0};
//Processo
printf ("Escolha o Método de aproximação:\n\n [1] Newton\n [2] Bissecção\n [3] Secante\n\n Escolha 1, 2 ou 3:\n\n");
scanf ("%d", opcao);
printf ("\n\nInsira extremo inferior do intervalo:\n");
scanf ("%f", a);
printf ("\nInsira extremo superior do intervalo:\n");
scanf ("%f", b);
a=((a+b)/2);
printf ("\nInsira a maior potência da equação:\n");
scanf ("%f", potencia);
for (i=0; i<=potencia; i++)
{
printf ("\nInsira coeficiente de x^%d:\n", i);
scanf ("%f", coef[i]);
}
printf ("\nSeu polinômio é:\n");
for (i=potencia; i>=0; i--){
printf ("+(%dx^%d)", coef[i], i);
printf ("\nInsira o erro máximo:\n");
}
scanf ("%f", erro);
switch (opcao) {
case 1:
i=0;
b=0;
printf("\n\n---------------------------------------\n");
printf("\n Iteração \t x \t F(x) \t \tF'(x) ");
printf("\n------------------------------------------\n");
do
{
cnt++;
f=fd=0;
for(i=potencia;i>=1;i--)
{
f+=coef[i] * (pow(a,i)) ;
}
f+=coef[0];
for(i=potencia;i>=0;i--)
{
fd+=coef[i]* (i*pow(a,(i-1)));
}
t=b;
b=(a-(f/fd));
a=b;
printf("\n\t %d \t%.3f \t %.3f\t\t%.3f ",cnt,b,f,fd);
}while((abs(t - a))>=erro);
printf("\n A Raiz aproximadamente é: %f",b);

break;
case 2:
i=0;
while ((b-a)/2>=erro)
{
printf ("\nA aproximação %d é: %f\n ", i, coef[i]);
for (i=potencia; i>=0; i--)
{
f=coef[i]*(pow(a,i))+f;
fd=coef[i]*(pow(t,i))+fd;
}
if (f*fd>0)
{
a=t;
t=((a+b)/2);
}
else
{
b=t;
t=((a+b)/2);
}
}
printf("\n A Raiz aproximadamente é: %f",t);
break;
case 3:
i=0;
for (i=potencia; i>=0; i--)
{
f=coef[i]*(pow(a,i))+f;
fd=coef[i]*(pow(b,i))+fd;
}
while((abs(f)>=erro))
{
t=b-((fd*(b-a))/(fd-f));
f=coef[i]*(pow(t,i))+f;
if (cnt<=150)
{
cnt++;
a=b;
b=t;
}
}
printf("\n A Raiz aproximadamente é: %f",t);
break;
default:
printf ("Escolher um método válido inserindo o 1, 2 ou 3:\n\n");
}
return 0;
}


  


2. Re: Metodo Newton, Bisseccao e Secante; AJUDA

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 14/12/2015 - 10:45h

Amigo, só algumas considerações:

*No printf para imprimir double é usado o %lf, para imprimir float é utilizado o %f

*No scanf segue a mesma lógica do printf, mas na hora de passar as variáveis, é necessário colocar o & na frente da variável [exceto se estiver utilizando ponteiros]. Exemplo:


double x;
printf("Digite um numero: ");
scanf("%lf",&x);


E nesse trecho:


for (i=potencia; i>=0; i--){
printf ("+(%lfx^%d)", coef[i], i);
printf ("\nInsira o erro máximo:\n");
}
scanf ("%lf", &erro);


Acho que houve um equívoco. Acho que o "Insira o erro máximo:" deveria estar fora do loop for.

Qualquer dúvida só postar!

Espero ter ajudado

[]'s

T+

--

Att,

Thiago Henrique Hüpner

(Mensagem scaneada pelo antivírus........ops! não precisa, afinal eu uso Linux!)



3. Fiz as modificações, mas não roda!=\

Renan
hqmac

(usa Outra)

Enviado em 14/12/2015 - 11:30h

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int main () {
printf ("Programa para Estimar Raízes\n\n");

//Declaração de Variáveis
double a=0, b=0, t=0, erro,f=0,fd=0;
int i=0, potencia=0, cnt=0, opcao=0;
double coef[15]={0};
//Processo
printf ("Escolha o Método de aproximação:\n\n [1] Newton\n [2] Bissecção\n [3] Secante\n\n Escolha 1, 2 ou 3:\n\n");
scanf ("%d", opcao);
printf ("\n\nInsira extremo inferior do intervalo:\n");
scanf ("%lf", &a);
printf ("\nInsira extremo superior do intervalo:\n");
scanf ("%lf", &b);
a=((a+b)/2);
printf ("\nInsira a maior potência da equação:\n");
scanf ("%lf", &potencia);
for (i=0; i<=potencia; i++)
{
printf ("\nInsira coeficiente de x^%d:\n", i);
scanf ("%lf", &coef[i]);
}
printf ("\nSeu polinômio é:\n");
for (i=potencia; i>=0; i--){
printf ("+(%lfx^%d)", coef[i], i);
}
printf ("\nInsira o erro máximo:\n");
scanf ("%lf", &erro);
switch (opcao) {
case 1:
i=0;
b=0;
printf("\n\n---------------------------------------\n");
printf("\n Iteração \t x \t F(x) \t \tF'(x) ");
printf("\n------------------------------------------\n");
do
{
cnt++;
f=fd=0;
for(i=potencia;i>=1;i--)
{
f+=coef[i] * (pow(a,i)) ;
}
f+=coef[0];
for(i=potencia;i>=0;i--)
{
fd+=coef[i]* (i*pow(a,(i-1)));
}
t=b;
b=(a-(f/fd));
a=b;
printf("\n\t %d \t%.3f \t %.3f\t\t%.3f ",cnt,b,f,fd);
}while((abs(t - a))>=erro);
printf("\n A Raiz aproximadamente é: %lf",b);

break;
case 2:
i=0;
while ((b-a)/2>=erro)
{
printf ("\nA aproximação %d é: %lf\n ", i, coef[i]);
for (i=potencia; i>=0; i--)
{
f=coef[i]*(pow(a,i))+f;
fd=coef[i]*(pow(t,i))+fd;
}
if (f*fd>0)
{
a=t;
t=((a+b)/2);
}
else
{
b=t;
t=((a+b)/2);
}
}
printf("\n A Raiz aproximadamente é: %lf",t);
break;
case 3:
i=0;
for (i=potencia; i>=0; i--)
{
f=coef[i]*(pow(a,i))+f;
fd=coef[i]*(pow(b,i))+fd;
}
while((abs(f)>=erro))
{
t=b-((fd*(b-a))/(fd-f));
f=coef[i]*(pow(t,i))+f;
if (cnt<=150)
{
cnt++;
a=b;
b=t;
}
}
printf("\n A Raiz aproximadamente é: %lf",t);
break;
default:
printf ("Escolher um método válido inserindo o 1, 2 ou 3:\n\n");
}
return 0;
}


4. Re: Metodo Newton, Bisseccao e Secante; AJUDA

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 14/12/2015 - 12:40h

Olá!

Com seu código, o compilador responde:


In function ‘main’:
14:1: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
scanf ("%d", opcao);
^
21:1: warning: format ‘%lf’ expects argument of type ‘double *’, but argument 2 has type ‘int *’ [-Wformat=]
scanf ("%lf", &potencia);
^


Falta colocar o & no primeiro e no segundo troque de %lf para %d

Se tiver algum erro que o compilador não acuse deve ser erro de lógica!

Nota: Coloque seu código entre as tags [code] e [/code], ficando assim:

[code]
Codigo...
[/code]

Espero ter ajudado

[]'s

T+

--

Att,

Thiago Henrique Hüpner

(Mensagem scaneada pelo antivírus........ops! não precisa, afinal eu uso Linux!)



5. Re: Metodo Newton, Bisseccao e Secante; AJUDA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 15/12/2015 - 05:31h

Thihup escreveu:

*No printf para imprimir double é usado o %lf, para imprimir float é utilizado o %f


Infelizmente, essa afirmação está errada.

Eu dou ênfase ao “infelizmente” porque realmente discordo da existência da regra, que me parece mais uma daquelas coisas socadas no padrão para acomodar compatibilidade com código antigo. A verdade, porém, é que em funções que recebem um número variável de argumentos, incluindo printf() e suas irmãs, um dado do tipo float que seja parte dos argumentos variáveis é sempre promovido a double. Do mesmo modo, todo valor integral de tamanho menor ou igual ao tamanho de um inteiro (bool, char ou short) é convertido para int.

Assim, o %f (ou %e, %g ou %a, bem como suas variantes em letra maiúscula) de printf() indica um valor do tipo double, sempre. A especificação %lf (e variantes com aAeEFgG) também denotam double (como o análogo em scanf()), mas é possível que o mais comum seja encontrar a formatação sem o “l”.

Note que a regra acima se aplica apenas aos argumentos na parte variável da lista de parâmetros; os que forem declarados com seus próprios tipos na assinatura da função continuam com as características que teriam variáveis comuns do mesmo tipo. Assim sendo, no código abaixo, ao ser invocada a função f(), o primeiro argumento continuará sendo um float dentro de f(), mas o segundo terá se tornado um double.

void f(float f, ...){
assert(sizeof f==sizeof(float)); // Vai funcionar

double d;
va_list params_d;
va_start(params_d, f);
d=va_arg(params_d, double);
assert(d==f); // Provavelmente vai funcionar (exceto problema de arredondamento).

float f2;
va_list params_f;
va_start(params_f, f);
f2=va_arg(params_f, float);
assert(f2==f); // Possivelmente vai falhar, a não ser que va_arg também converta float em double
}

void g(void){
float f1, f2;
f1=f2=1.23456789;
f(f1, f2); // f1 segue como float; f2 é convertido em double antes de chamar f()
}


Aliás, na hora de compilar aqui, o GCC chiou, mas deixou passar.

In file included from d.c:2:0:
d.c: In function ‘f’:
d.c:18:22: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ [enabled by default]
f2=va_arg(params_f, float);
^
d.c:18:22: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)
d.c:18:22: note: if this code is reached, the program will abort


Em tempo, se você quiser trabalhar com long double, o modificador da conversão será L (maiúsculo).

*No scanf segue a mesma lógica do printf, mas na hora de passar as variáveis, é necessário colocar o & na frente da variável [exceto se estiver utilizando ponteiros].


Bem, como vimos acima, a lógica é um pouco diferente.

Lembrando um pouco dos fundamentos, todos os parâmetros de função em C são sempre passados por valor. Isso significa, por exemplo, que se eu tenho duas variáveis a e b de tipos quaisquer e uma função f(), uma chamada do tipo f(a,b) vai copiar os valores de a e de b para uma região de memória que seja visível de dentro de f(), e então invocar a execução de f(). Como a função trabalha com cópias, qualquer alteração que ela faça sobre os valores que ela recebeu não se reflete nos dados originais.

Para que uma função consiga modificar valores que lhe são externos, a técnica que se usa em C é aplicar o operador unário & ao dado que se quer modificar, pois essa operação devolve o endereço de onde o dado está armazenado (i.e. um ponteiro), e então passar o valor desse endereço como argumento para a função. Faz sentido: afinal, se um ponteiro aponta para um determinado lugar da memória, a cópia desse ponteiro aponta para a mesma posição. Dentro da função, então, utiliza-se o operador unário *, que é faz o inverso do que faz &, ou seja, chega a um dado não-temporário a partir do seu endereço e do seu tipo.

Sabendo isso, pode-se entender o porquê de scanf() ter diferenças em relação a printf(). Ambas possuem um primeiro parâmetro fixo, que diz como os demais, que têm forma variável (podendo até mesmo eventualmente não existir), devem ser interpretados. No entanto, os argumentos variáveis de printf(), interpretados de acordo com a formatação, são cópias dos valores dos dados, ao passo que para scanf() eles são cópias dos endereços em que os dados devem residir após operação de leitura bem sucedida.

Assim, não existe promoção de float para double (nem de char para int, nem qualquer outra) com scanf(), simplesmente porque scanf() nunca recebe um float (ou char, ou o que quer que seja), mas tão somente ponteiros para dados que podem ser desses tipos. Lá dentro da função é que, de acordo com a string de formatação, o argumento será interpretado como sendo um ponteiro para float, e então o dado será manipulado de acordo com as regras específicas desse tipo, e gravado na respectiva região de memória referenciada pelo ponteiro.


6. Re: Metodo Newton, Bisseccao e Secante; AJUDA

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 15/12/2015 - 09:29h

Obrigado pelos esclarecimentos Paulo!

Isso já me tirou algumas dúvidas que tinha quanto a cópia dos valores e etc.

Muito Obrigado

[]'s

T+

--

Att,

Thiago Henrique Hüpner

(Mensagem scaneada pelo antivírus........ops! não precisa, afinal eu uso Linux!)







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts