Oppure

Loading
13/01/10 16:32
Puffetta
Ciao a tutti!!!!!! Ho fatto dei programmi per trovare gli zeri di una funzione mediante i metodi di bisezione, Newton e secanti e funzionavano tutti benissimo. Ora però mi è stato chiesto di fare un programma per trovare gli zeri delle funzioni che permetta all'utente di scegliere quale metodo utilizzare. Ho fatto il codice, solo che ora c'è un problema: i risultati(soprattutto bisezione e secante) non convergono alla soluzione! qualcuno saprebbe dirmi dove ho sbagliato e perchè queste soluzioni non convergono?
Questo è il codice che ho fatto io

/*Scrivere un programma C++ che realizza il metodo di bisezione, il metodo di Newton e il metodo della secante e utilizzarlo per
approssimare entro la tolleranza acquisita da tastiera le radici di alcune equazioni non lineari.*/

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

double f(double, int);
int leggif();
int leggimet();
void METODO1(int);
double bisezione(double, double, double, double, int, int);
void METODO2(int);
double fp(double, int);
double newton(double, double, int, int &, int);
void METODO3(int);
double secanti(double, double, double, double, double, int, int);

main()
{
      int contr, metodo;
      
      contr=leggif();
      
      metodo=leggimet();
      
      if(metodo==1)
                  METODO1(contr);
     
      else if(metodo==2)         
                  METODO2(contr);
      
      else if(metodo==3)         
                  METODO3(contr);
                  
      else if(metodo==4)
                 {
                        METODO1(contr);
                        
                        METODO2(contr);
                        
                        METODO3(contr);
                 }      
     
      system("PAUSE");
      return 0;      
}

int leggif()
{
    int a; 
    
    printf("\n\n Di quali tra le funzioni 1-2-3-4-5-6-7 voglio conoscere gli zeri?\n funzione n.");
    scanf("%d", &a);
    
    return a;
}

double f(double t, int contr)
{      
       if(contr==1)
                   return(t*t-2);
                   
       else if(contr==2)
                   return(t*t*t-2);
       
       else if(contr==3)
                   return((t*t*t)-2*(t*t)+3*t-4);
       
       else if(contr==4)
                    return((t*t*t*t*t)-6*(t*t*t)+3);
       
       else if(contr==5)
                   return(1-2*t*exp(-t/2));
       
       else if(contr==6)
                   return(t-exp(-t*t));
                   
       else if(contr==7)
                   return(log(t)+t);
}

int leggimet()
{
    int c;
    
    printf("\n\n Per trovare gli zeri di una funzione ci sono vari metodi");
    printf("\n\n Per scegliere il metodo di bisezione digita il numero 1");
    printf("\n\n Per scegliere il metodo di Newton digita il numero 2");
    printf("\n\n Per scegliere il metodo delle secanti digita il numero 3");
    printf("\n\n Per scegliere tutti i metodi di risoluzioni digita il numero 4");
    printf("\n\n Quale metodo vuoi usare per trovare gli zeri della funzione?     ");
    scanf("%d", &c);
    
    return c;
}

void METODO1(int contr)
{
     double a, b, c, fa, fb;
     
     printf("\n\n Qual'e' il valore di a?");
     scanf("%lf", &a);
      
     printf("\n Qual'e' il valore di b?");
     scanf("%lf", &b);
     
     fa=f(a, contr);
      
     fb=f(b, contr);
      
     if(fa*fb>0)
                 {
                     printf("\n La radice non si trova in questo intervallo\n");
                     return;
                 }
      
     else if(fa==0)
                 {
                     printf("\n Lo zero della funzione è l'estremo a, cioè c=a=%lf\n", a);
                     return;
                 }
      
      else if(fb==0)
                 {
                     printf("\n Lo zero della funzione è l'estremo b, cioè c=b=%lf\n", b);
                     return;
                 }
      
      else if(fa*fb<0)
                 {
                      double eps; int k;
                      
                      printf("\n Inserisci il valore della tolleranza eps=");
                      scanf("%lf", &eps);
                      
                      printf("\n In quante iterazioni si deve raggiungere il risultato? k=");
                      scanf("%d", &k);
                      
                      c=bisezione(a, b, fa, fb, k, contr);
                      
                      printf("\n\n Lo zero della funzione calcolato mediante il metodo della bisezione e' uguale a x=%1.16f\n", c);
                 }
      
      return;
}

double bisezione(double a, double b, double fa, double fb, int k, int contr)
{
       double c, fc;
       
       for(int i=1; i<=k; i++)
               {
                    c=a+(b-a)/2;//1°funzione sbagliata
                    
                    fc=f(c, contr);
                    
                    if(fa*fc<0)
                          {
                               b=c;
                               
                               fb=fc;
                          }
                    
                    else if(fc==0)
                          {
                               printf("\n\n La radice e' uguale a c, cioe' vale c=%.16f\n\n", c);
                               return 0;
                          }
                    else if(fa*fc>0)
                          {
                                a=c;
                                
                                fa=fc;
                          }
               }
       
       return c;       
}

void METODO2(int contr)
{
       double xk, fx, fpx, x, delta, toll; int nmax, n=1;
       
       printf("\n\n Inserire un numero reale    xk=");
       scanf("%lf", &xk);
      
       printf("\n Inserire il limite di precisione    toll=");
       scanf("%lf", &toll);
      
       printf("\n Quante iterazioni al massimo posso fare?    n=");
       scanf("%d", &nmax);
       
       x=newton(xk,toll, nmax, n, contr);
       
       printf("\n\n La radice e' uguale a x=%1.16f\n\n", x);
     
       printf("\n Il numero di iterate fatte e' uguale a %d\n\n", n);
       
       return;
}

double newton(double xk, double toll, int k,int & n, int contr)
{
     double fxk, fpxk, delta;
     
     do
       {    
            fxk=f(xk, contr);
             
            fpxk=fp(xk, contr);
             
            delta=fxk/fpxk;
             
            xk -= delta;
             
            n++;           
       }
     while(((delta+fabs(fxk))<toll)||(n<k));
     
     return xk;    
}

double fp(double x, int contr)
{
       if(contr==1)
                   return (2*x);
                   
       else if(contr==2)
                   return (2*(x*x));
       
       else if(contr==3)
                   return(3*x*x-4*x+3);
       
       else if(contr==4)
                   return(5*x*x*x*x-18*x*x);
       
       else if(contr==5)
                   return((x*exp(-x/2))-(2*exp(-x/2)));
       
       else if(contr==6)
                   return(1+2*x*exp(-x*x));
                   
       else if(contr==7)
                   return((1/x)+1);
}



void METODO3(int contr)
{
      double x0, x1, f0, f1, x, toll; int k;
      
      printf("\n\n Inserire il valore   x0=");
      scanf("%lf", &x0);
      
      printf("\n\n Inserire il valore   x1=");
      scanf("%lf", &x1);
      
      printf("\n Inserisci il valore della tolleranza   toll=");
      scanf("%lf", &toll);
                      
      printf("\n In quante iterazioni si deve raggiungere il risultato? k=");
      scanf("%d", &k);
      
      f0=f(x0, contr);
      
      f1=f(x1, contr);
      
      x=secanti(x0, x1, f0, f1, toll, k, contr);
      
      printf("\n La radice trovata con il metodo delle secanti e' uguale a x=%1.16f\n", x);
      
      return;
}

double secanti(double x0, double x1, double f0, double f1, double toll, int k, int contr)
{
       double x, fx, delta; int cont=0;// cont mi permette di controllare il numero delle iterate
       
       do
         {
              x=x1-(f1*(x1-x0)/(f1-f0));//calcola x n+1 e successivamente f(x n+1)
         
              fx=f(x, contr);
              
              x1=x;
              
              f1=fx;
              
              delta=fabs(x1-x0);
              
              cont++;
             
         }
       while((delta<toll)||(cont<k));
       
       return x;
}


Scusate ma è veramente importante e non so più che fare:d grazie
aaa
13/01/10 17:49
matteog
non si capisce quali sono le funzioni su cui lavora senza conoscerle come faccio a capire cosa devo fare?? posta degli esempi con le varie funzioni e i vari metodi che vedo di risolvere il probelma
aaa
13/01/10 21:38
lorenzo
a parte il fatto che è C e non C++...comunque la domanda a cui devi rispondere è: prima che mettessi la scelta andava tutto bene?

SI: allora il problema sta nel codice che hai aggiunto, prova a fare il debug controllando i valori che passi alle funzioni.

NO: allora devi ricontrollare le funzioni che hai scritto, sinceramente non ho molta voglia di stare a controllare i tuoi calcoli, prova ad eliminare pezzi di programma e provare ogni metodo separatamente.
aaa
13/01/10 21:40
matteog
ho guardato il codice credo siano quei parametri di ritorno ma nn conosco molto bene l'argomento quindi non sò dove mettere le mani forse ti conviene lavorare su tt e tre separatamente e poi unirli in uno solo!
aaa