Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Trovare lo zero di una funzione
Forum - C/C++ - Trovare lo zero di una funzione

Avatar
Puffetta (Normal User)
Rookie


Messaggi: 21
Iscritto: 29/11/2009

Segnala al moderatore
Postato alle 17:32
Mercoledì, 13/01/2010
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

Codice sorgente - presumibilmente C#

  1. /*Scrivere un programma C++ che realizza il metodo di bisezione, il metodo di Newton e il metodo della secante e utilizzarlo per
  2. approssimare entro la tolleranza acquisita da tastiera le radici di alcune equazioni non lineari.*/
  3.  
  4. #include<stdio.h>
  5. #include<stdlib.h>
  6. #include<math.h>
  7.  
  8. double f(double, int);
  9. int leggif();
  10. int leggimet();
  11. void METODO1(int);
  12. double bisezione(double, double, double, double, int, int);
  13. void METODO2(int);
  14. double fp(double, int);
  15. double newton(double, double, int, int &, int);
  16. void METODO3(int);
  17. double secanti(double, double, double, double, double, int, int);
  18.  
  19. main()
  20. {
  21.       int contr, metodo;
  22.      
  23.       contr=leggif();
  24.      
  25.       metodo=leggimet();
  26.      
  27.       if(metodo==1)
  28.                   METODO1(contr);
  29.      
  30.       else if(metodo==2)        
  31.                   METODO2(contr);
  32.      
  33.       else if(metodo==3)        
  34.                   METODO3(contr);
  35.                  
  36.       else if(metodo==4)
  37.                  {
  38.                         METODO1(contr);
  39.                        
  40.                         METODO2(contr);
  41.                        
  42.                         METODO3(contr);
  43.                  }      
  44.      
  45.       system("PAUSE");
  46.       return 0;      
  47. }
  48.  
  49. int leggif()
  50. {
  51.     int a;
  52.    
  53.     printf("\n\n Di quali tra le funzioni 1-2-3-4-5-6-7 voglio conoscere gli zeri?\n funzione n.");
  54.     scanf("%d", &a);
  55.    
  56.     return a;
  57. }
  58.  
  59. double f(double t, int contr)
  60. {      
  61.        if(contr==1)
  62.                    return(t*t-2);
  63.                    
  64.        else if(contr==2)
  65.                    return(t*t*t-2);
  66.        
  67.        else if(contr==3)
  68.                    return((t*t*t)-2*(t*t)+3*t-4);
  69.        
  70.        else if(contr==4)
  71.                     return((t*t*t*t*t)-6*(t*t*t)+3);
  72.        
  73.        else if(contr==5)
  74.                    return(1-2*t*exp(-t/2));
  75.        
  76.        else if(contr==6)
  77.                    return(t-exp(-t*t));
  78.                    
  79.        else if(contr==7)
  80.                    return(log(t)+t);
  81. }
  82.  
  83. int leggimet()
  84. {
  85.     int c;
  86.    
  87.     printf("\n\n Per trovare gli zeri di una funzione ci sono vari metodi");
  88.     printf("\n\n Per scegliere il metodo di bisezione digita il numero 1");
  89.     printf("\n\n Per scegliere il metodo di Newton digita il numero 2");
  90.     printf("\n\n Per scegliere il metodo delle secanti digita il numero 3");
  91.     printf("\n\n Per scegliere tutti i metodi di risoluzioni digita il numero 4");
  92.     printf("\n\n Quale metodo vuoi usare per trovare gli zeri della funzione?     ");
  93.     scanf("%d", &c);
  94.    
  95.     return c;
  96. }
  97.  
  98. void METODO1(int contr)
  99. {
  100.      double a, b, c, fa, fb;
  101.      
  102.      printf("\n\n Qual'e' il valore di a?");
  103.      scanf("%lf", &a);
  104.      
  105.      printf("\n Qual'e' il valore di b?");
  106.      scanf("%lf", &b);
  107.      
  108.      fa=f(a, contr);
  109.      
  110.      fb=f(b, contr);
  111.      
  112.      if(fa*fb>0)
  113.                  {
  114.                      printf("\n La radice non si trova in questo intervallo\n");
  115.                      return;
  116.                  }
  117.      
  118.      else if(fa==0)
  119.                  {
  120.                      printf("\n Lo zero della funzione è l'estremo a, cioè c=a=%lf\n", a);
  121.                      return;
  122.                  }
  123.      
  124.       else if(fb==0)
  125.                  {
  126.                      printf("\n Lo zero della funzione è l'estremo b, cioè c=b=%lf\n", b);
  127.                      return;
  128.                  }
  129.      
  130.       else if(fa*fb<0)
  131.                  {
  132.                       double eps; int k;
  133.                      
  134.                       printf("\n Inserisci il valore della tolleranza eps=");
  135.                       scanf("%lf", &eps);
  136.                      
  137.                       printf("\n In quante iterazioni si deve raggiungere il risultato? k=");
  138.                       scanf("%d", &k);
  139.                      
  140.                       c=bisezione(a, b, fa, fb, k, contr);
  141.                      
  142.                       printf("\n\n Lo zero della funzione calcolato mediante il metodo della bisezione e' uguale a x=%1.16f\n", c);
  143.                  }
  144.      
  145.       return;
  146. }
  147.  
  148. double bisezione(double a, double b, double fa, double fb, int k, int contr)
  149. {
  150.        double c, fc;
  151.        
  152.        for(int i=1; i<=k; i++)
  153.                {
  154.                     c=a+(b-a)/2;//1°funzione sbagliata
  155.                    
  156.                     fc=f(c, contr);
  157.                    
  158.                     if(fa*fc<0)
  159.                           {
  160.                                b=c;
  161.                                
  162.                                fb=fc;
  163.                           }
  164.                    
  165.                     else if(fc==0)
  166.                           {
  167.                                printf("\n\n La radice e' uguale a c, cioe' vale c=%.16f\n\n", c);
  168.                                return 0;
  169.                           }
  170.                     else if(fa*fc>0)
  171.                           {
  172.                                 a=c;
  173.                                
  174.                                 fa=fc;
  175.                           }
  176.                }
  177.        
  178.        return c;      
  179. }
  180.  
  181. void METODO2(int contr)
  182. {
  183.        double xk, fx, fpx, x, delta, toll; int nmax, n=1;
  184.        
  185.        printf("\n\n Inserire un numero reale    xk=");
  186.        scanf("%lf", &xk);
  187.      
  188.        printf("\n Inserire il limite di precisione    toll=");
  189.        scanf("%lf", &toll);
  190.      
  191.        printf("\n Quante iterazioni al massimo posso fare?    n=");
  192.        scanf("%d", &nmax);
  193.        
  194.        x=newton(xk,toll, nmax, n, contr);
  195.        
  196.        printf("\n\n La radice e' uguale a x=%1.16f\n\n", x);
  197.      
  198.        printf("\n Il numero di iterate fatte e' uguale a %d\n\n", n);
  199.        
  200.        return;
  201. }
  202.  
  203. double newton(double xk, double toll, int k,int & n, int contr)
  204. {
  205.      double fxk, fpxk, delta;
  206.      
  207.      do
  208.        {    
  209.             fxk=f(xk, contr);
  210.              
  211.             fpxk=fp(xk, contr);
  212.              
  213.             delta=fxk/fpxk;
  214.              
  215.             xk -= delta;
  216.              
  217.             n++;          
  218.        }
  219.      while(((delta+fabs(fxk))<toll)||(n<k));
  220.      
  221.      return xk;    
  222. }
  223.  
  224. double fp(double x, int contr)
  225. {
  226.        if(contr==1)
  227.                    return (2*x);
  228.                    
  229.        else if(contr==2)
  230.                    return (2*(x*x));
  231.        
  232.        else if(contr==3)
  233.                    return(3*x*x-4*x+3);
  234.        
  235.        else if(contr==4)
  236.                    return(5*x*x*x*x-18*x*x);
  237.        
  238.        else if(contr==5)
  239.                    return((x*exp(-x/2))-(2*exp(-x/2)));
  240.        
  241.        else if(contr==6)
  242.                    return(1+2*x*exp(-x*x));
  243.                    
  244.        else if(contr==7)
  245.                    return((1/x)+1);
  246. }
  247.  
  248.  
  249.  
  250. void METODO3(int contr)
  251. {
  252.       double x0, x1, f0, f1, x, toll; int k;
  253.      
  254.       printf("\n\n Inserire il valore   x0=");
  255.       scanf("%lf", &x0);
  256.      
  257.       printf("\n\n Inserire il valore   x1=");
  258.       scanf("%lf", &x1);
  259.      
  260.       printf("\n Inserisci il valore della tolleranza   toll=");
  261.       scanf("%lf", &toll);
  262.                      
  263.       printf("\n In quante iterazioni si deve raggiungere il risultato? k=");
  264.       scanf("%d", &k);
  265.      
  266.       f0=f(x0, contr);
  267.      
  268.       f1=f(x1, contr);
  269.      
  270.       x=secanti(x0, x1, f0, f1, toll, k, contr);
  271.      
  272.       printf("\n La radice trovata con il metodo delle secanti e' uguale a x=%1.16f\n", x);
  273.      
  274.       return;
  275. }
  276.  
  277. double secanti(double x0, double x1, double f0, double f1, double toll, int k, int contr)
  278. {
  279.        double x, fx, delta; int cont=0;// cont mi permette di controllare il numero delle iterate
  280.        
  281.        do
  282.          {
  283.               x=x1-(f1*(x1-x0)/(f1-f0));//calcola x n+1 e successivamente f(x n+1)
  284.          
  285.               fx=f(x, contr);
  286.              
  287.               x1=x;
  288.              
  289.               f1=fx;
  290.              
  291.               delta=fabs(x1-x0);
  292.              
  293.               cont++;
  294.              
  295.          }
  296.        while((delta<toll)||(cont<k));
  297.        
  298.        return x;
  299. }



Scusate ma è veramente importante e non so più che fare:d grazie

PM Quote
Avatar
matteog (Normal User)
Pro


Messaggi: 149
Iscritto: 10/04/2009

Segnala al moderatore
Postato alle 18:49
Mercoledì, 13/01/2010
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

PM Quote
Avatar
lorenzo (Normal User)
Guru


Messaggi: 1178
Iscritto: 15/04/2008

Segnala al moderatore
Postato alle 22:38
Mercoledì, 13/01/2010
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.

PM Quote
Avatar
matteog (Normal User)
Pro


Messaggi: 149
Iscritto: 10/04/2009

Segnala al moderatore
Postato alle 22:40
Mercoledì, 13/01/2010
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!

PM Quote