Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

di il
14 risposte

Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

Buonasera.Ho scritto il seguente codice per approssimare lo zero di f(x)=logx+x con il metodo di Newton,ma il codice si pianta quando viene eseguito(in compilazione,apparentemente,non dà errori).Non so davvero dove sbattere la testa.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define TOLL 1.e-5
#define MAXITERAZIONI 100
void letturanumerireali_ab(double&,double&);
double estremodifourier(double&,double&,double);
int newton(double&,double);
int main(){
printf("Programma C++ che legge due numeri reali a e b,con a<b(estremi dell'intervallo in cui lo zero di f(x)=logx+x e'stato precedentemente localizzato e separato)e l'estremo di Fourier,cioe' l'approssimazione iniziale dello zero;stampa il numero di iterazioni compiute dal metodo di Newton per approssimare lo zero con errore minore di 10^-5\n(preventivando al massimo 100 iterazioni)e il valore approssimato dello zero fornito dal metodo\n");
double a,b;
letturanumerireali_ab(a,b);/*inserimento dei due reali a e b(a<b)estremi dell'intervallo in cui si trova lo zero di f(x):lo zero semplice di
                             f(x)appartiene ad [a,b]*/
/*Tramite gnuplot si vede,dal grafico della funzione,che lo zero semplice di f(x)=logx+x(inserita su gnuplot come x-exp(-x)) 
è circa x=0.567143*/
double x0;//estremo di Fourier dell'intervallo [a,b]
estremodifourier(a,b,x0);
double x;//zero approssimato della funzione
int iterazioni=newton(x0,TOLL);//metodo di Newton(restituisce,come risultato,il numero di iterazioni eseguite)
printf("L'approssimazione dello zero di f(x)=logx+x calcolata tramite il metodo di Newton e':%lf\n",x);
printf("Il numero di iterazioni eseguite per approssimare lo zero di f(x)=logx+x tramite il metodo di Newton e' %d\n",iterazioni);
return 0;
}
//Inserimento di due numeri reali a e b,con a<b,in cui sarà stato precedentemente localizzato e separato lo zero:
void letturanumerireali_ab(double& a,double& b){
printf("Lo zero semplice della funzione f(x)=logx+x(calcolato con gnuplot),appartenente ad [a,b],e' uguale ad x=0.567143\n");
do{printf("Inserire il numero reale a,tale che a<b:\n");scanf("%lf",&a);
printf("Inserire il numero reale b,tale che a<b:\n");scanf("%lf",&b);}
	while(b<=a);
return;
}
//Calcolo dell'estremo di Fourier della funzione nell'intervallo [a,b] (esso rappresenterà l'approssimazione iniziale dello zero di f(x) ):
double estremodifourier(double& a,double& b,double estremo)
{
/*Per calcolare l'estremo di Fourier,devono essere verificate le ipotesi EF,secondo cui in [a,b]: f(x)sia di classe C1([a,b]),f(a)*f(b)<0,e
f(x) sia convessa,o concava,in [a,b] (cioè f'(x) sia non crescente,o non decrescente,in [a,b]).In questo caso,f(x)=logx+x è di classe 
C1([a,b]).Proseguendo con le altre ipotesi,si ha:*/
if((log(a)+a)*(log(b)+b)<0)
{/*Se f(a)*f(b)<0,si procede con la verifica dell'ultima ipotesi,secondo cui f(x) sia convessa o concava in [a,b].Per farlo,si utilizza la
derivata prima di f(x),cioè f'(x)=1/x + 1.Questa è monotona decrescente(quindi non crescente)nell'intorno [a,b](preso piccolo) dello zero 
0.567143 di f(x),quindi è convessa in [a,b].Si prosegue quindi con il calcolo dell'estremo di Fourier x(0).
Per calcolare quale tra i due punti a e b sia l'estremo x(0) di Fourier dal quale partire con l'approssimazione dello zero di f(x),si deve
calcolare la derivata seconda f''(x) della funzione,che sarà uguale a f''(x)=-1/x^2.
Successivamente,per calcolare effettivamente l'estremo di Fourier,si calcola il prodotto tra f(x) e f''(x) nei punti a e b,e si effettua la
seguente scelta:*/
if((log(a)+a)*(-1/pow(a,2))>0) estremo=a; //se f(a)*f''(a)>0 l'estremo di Fourier x(0) sarà uguale all'estremo a di [a,b]
else estremo=b; //altrimenti,cioè se f(b)*f''(b)>0,l'estremo di Fourier x(0) sarà uguale all'estremo b di [a,b]
return estremo;}
else {printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
      return 1;}
}
//Calcolo dell'approssimazione x(i) dello zero di f(x)=logx+x e del numero di iterazioni eseguite,tramite il metodo di Newton:
int newton(double&estremo,double tau){
/*Si passa una variabile(l'estremo x(0) )per indirizzo perché la funzione deve restituire due output,cioè la soluzione approssimata e il 
numero di iterazioni eseguite,e in genere una funzione può restituirne solo uno.*/
int cont=0;//contatore del numero di iterazioni che si eseguiranno nel metodo di Newton
double delta;//variabile che servirà per verificare la condizione del criterio di arresto del metodo,cioè |delta|<tau
double xi=estremo;//dichiarazione di x(i),che all'inizio sarà x(0),cioè l'estremo di Fourier
double x_imeno1;//dichiarazione di x(i-1) del passo precedente dell'iterazione di Newton
do{x_imeno1=xi; 
   xi=x_imeno1-((log(x_imeno1)+x_imeno1)/((1/x_imeno1)+1)); //x(i)=x(i-1)- f(x(i-1))/f'(x(i-1))
   delta=fabs((xi-x_imeno1));
   cont++;
  }
 while((delta<tau)||(cont<MAXITERAZIONI));/*condizione di arresto del metodo di Newton:si va avanti finché |x(i)-x(i-1)|<TOLL o finché 
                                         il numero di iterazioni non sia al massimo 100*/
return cont;
}

14 Risposte

  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Veramente in compilazione dice che x0 e x sono usati ma non inizializzati
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    E allora il mio compilatore fa schifo
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Ok,ora stampa l'approssimazione e il numero di iterate. Le iterate non saprei(me le stampa a prescindere uguali a 100),l'approssimazione la mette uguale a 0.000000000( e non credo sia corretta(la soluzione "esatta" dovrebbe essere circa 0.567143).Almeno fa qualcosa adesso ahah.Ma non è comunque giusto
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    @Oregon Ho provato a modificare qualcosa,ma ancora niente.
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #define TOLL 1.e-5
    #define MAXITERAZIONI 100
    void letturanumerireali_ab(double&,double&);
    double estremodifourier(double&,double&,double&);
    int newton(double&,double);
    int main(){
    printf("Programma C++ che legge due numeri reali a e b,con a<b(estremi dell'intervallo in cui lo zero di f(x)=logx+x e'stato precedentemente localizzato e separato)e l'estremo di Fourier,cioe' l'approssimazione iniziale dello zero;stampa il numero di iterazioni compiute dal metodo di Newton per approssimare lo zero con errore minore di 10^-5\n(preventivando al massimo 100 iterazioni)e il valore approssimato dello zero fornito dal metodo\n");
    double a,b;
    letturanumerireali_ab(a,b);/*inserimento dei due reali a e b(a<b)estremi dell'intervallo in cui si trova lo zero di f(x):lo zero 
                                semplice di f(x)appartiene ad [a,b]*/
    /*Tramite gnuplot si vede,dal grafico della funzione,che lo zero semplice di f(x)=logx+x(inserita su gnuplot come x-exp(-x)) 
    è circa x=0.567143*/
    double x0;//estremo di Fourier dell'intervallo [a,b]
    estremodifourier(a,b,x0);
    double xi;//zero approssimato della funzione
    int iterazioni=newton(x0,TOLL);//metodo di Newton(restituisce,come risultato,il numero di iterazioni eseguite)
    printf("L'approssimazione dello zero di f(x)=logx+x calcolata tramite il metodo di Newton e':%lf\n",xi);
    printf("Il numero di iterazioni eseguite per approssimare lo zero di f(x)=logx+x tramite il metodo di Newton e' %d\n",iterazioni);
    return 0;
    }
    //Inserimento di due numeri reali a e b,con a<b,in cui sarà stato precedentemente localizzato e separato lo zero:
    void letturanumerireali_ab(double& a,double& b){
    printf("Lo zero semplice della funzione f(x)=logx+x(calcolato con gnuplot),appartenente ad [a,b],e' uguale ad x=0.567143\n");
    do{printf("Inserire il numero reale a,tale che a<b:\n");scanf("%lf",&a);
    printf("Inserire il numero reale b,tale che a<b:\n");scanf("%lf",&b);}
    	while(b<=a);
    return;
    }
    //Calcolo dell'estremo di Fourier della funzione nell'intervallo [a,b] (esso rappresenterà l'approssimazione iniziale dello zero di f(x) ):
    double estremodifourier(double& a,double& b,double& estremo)
    {
    /*Per calcolare l'estremo di Fourier,devono essere verificate le ipotesi EF,secondo cui in [a,b]: f(x)sia di classe C1([a,b]),f(a)*f(b)<0,e
    f(x) sia convessa,o concava,in [a,b] (cioè f'(x) sia non crescente,o non decrescente,in [a,b]).In questo caso,f(x)=logx+x è di classe 
    C1([a,b]).Proseguendo con le altre ipotesi,si ha:*/
    if((log(a)+a)*(log(b)+b)<0)
    {/*Se f(a)*f(b)<0,si procede con la verifica dell'ultima ipotesi,secondo cui f(x) sia convessa o concava in [a,b].Per farlo,si utilizza la
    derivata prima di f(x),cioè f'(x)=1/x + 1.Questa è monotona decrescente(quindi non crescente)nell'intorno [a,b](preso piccolo) dello zero 
    0.567143 di f(x),quindi è convessa in [a,b].Si prosegue quindi con il calcolo dell'estremo di Fourier x(0).
    Per calcolare quale tra i due punti a e b sia l'estremo x(0) di Fourier dal quale partire con l'approssimazione dello zero di f(x),si deve
    calcolare la derivata seconda f''(x) della funzione,che sarà uguale a f''(x)=-1/x^2.
    Successivamente,per calcolare effettivamente l'estremo di Fourier,si calcola il prodotto tra f(x) e f''(x) nei punti a e b,e si effettua la
    seguente scelta:*/
    if((log(a)+a)*(-1*(-1/pow(a,2)))>0) estremo=a; //se f(a)*f''(a)>0 l'estremo di Fourier x(0) sarà uguale all'estremo a di [a,b]
    else estremo=b; //altrimenti,cioè se f(b)*f''(b)>0,l'estremo di Fourier x(0) sarà uguale all'estremo b di [a,b]
    return estremo;}
    else {printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
          return 1;}
    }
    //Calcolo dell'approssimazione x(i) dello zero di f(x)=logx+x e del numero di iterazioni eseguite,tramite il metodo di Newton:
    int newton(double&estremodifourier,double tau){
    /*Si passa una variabile(l'estremo x(0) )per indirizzo perché la funzione deve restituire due output,cioè la soluzione approssimata e il 
    numero di iterazioni eseguite,e in genere una funzione può restituirne solo uno.*/
    int cont=0;//contatore del numero di iterazioni che si eseguiranno nel metodo di Newton
    double delta;//variabile che servirà per verificare la condizione del criterio di arresto del metodo,cioè |delta|<tau
    double xi=estremodifourier;//dichiarazione di x(i),che all'inizio sarà x(0),cioè l'estremo di Fourier
    double x_imeno1;//dichiarazione di x(i-1) del passo precedente dell'iterazione di Newton
    do{x_imeno1=xi; 
       xi=x_imeno1-((log(x_imeno1)+x_imeno1)/((1/x_imeno1)+1));//x(i)=x(i-1)- f(x(i-1))/f'(x(i-1))
       delta=fabs((xi-x_imeno1));
       cont++;
      }
     while((delta<tau)&&(cont<MAXITERAZIONI));/*condizione di arresto del metodo di Newton:si va avanti finché |x(i)-x(i-1)|<TOLL e finché 
                                              il numero di iterazioni non è al massimo 100*/
    return cont;
    }
    
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    MaximusMeridius ha scritto:


    @Oregon Ho provato a modificare qualcosa,ma ancora niente.
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #define TOLL 1.e-5
    #define MAXITERAZIONI 100
    void letturanumerireali_ab(double&,double&);
    double estremodifourier(double&,double&,double&);
    int newton(double&,double);
    int main(){
    printf("Programma C++ che legge due numeri reali a e b,con a<b(estremi dell'intervallo in cui lo zero di f(x)=logx+x e'stato precedentemente localizzato e separato)e l'estremo di Fourier,cioe' l'approssimazione iniziale dello zero;stampa il numero di iterazioni compiute dal metodo di Newton per approssimare lo zero con errore minore di 10^-5\n(preventivando al massimo 100 iterazioni)e il valore approssimato dello zero fornito dal metodo\n");
    double a,b;
    letturanumerireali_ab(a,b);/*inserimento dei due reali a e b(a<b)estremi dell'intervallo in cui si trova lo zero di f(x):lo zero 
                                semplice di f(x)appartiene ad [a,b]*/
    /*Tramite gnuplot si vede,dal grafico della funzione,che lo zero semplice di f(x)=logx+x(inserita su gnuplot come x-exp(-x)) 
    è circa x=0.567143*/
    double x0;//estremo di Fourier dell'intervallo [a,b]
    estremodifourier(a,b,x0);
    double xi;//zero approssimato della funzione
    int iterazioni=newton(x0,TOLL);//metodo di Newton(restituisce,come risultato,il numero di iterazioni eseguite)
    printf("L'approssimazione dello zero di f(x)=logx+x calcolata tramite il metodo di Newton e':%lf\n",xi);
    printf("Il numero di iterazioni eseguite per approssimare lo zero di f(x)=logx+x tramite il metodo di Newton e' %d\n",iterazioni);
    return 0;
    }
    //Inserimento di due numeri reali a e b,con a<b,in cui sarà stato precedentemente localizzato e separato lo zero:
    void letturanumerireali_ab(double& a,double& b){
    printf("Lo zero semplice della funzione f(x)=logx+x(calcolato con gnuplot),appartenente ad [a,b],e' uguale ad x=0.567143\n");
    do{printf("Inserire il numero reale a,tale che a<b:\n");scanf("%lf",&a);
    printf("Inserire il numero reale b,tale che a<b:\n");scanf("%lf",&b);}
    	while(b<=a);
    return;
    }
    //Calcolo dell'estremo di Fourier della funzione nell'intervallo [a,b] (esso rappresenterà l'approssimazione iniziale dello zero di f(x) ):
    double estremodifourier(double& a,double& b,double& estremo)
    {
    /*Per calcolare l'estremo di Fourier,devono essere verificate le ipotesi EF,secondo cui in [a,b]: f(x)sia di classe C1([a,b]),f(a)*f(b)<0,e
    f(x) sia convessa,o concava,in [a,b] (cioè f'(x) sia non crescente,o non decrescente,in [a,b]).In questo caso,f(x)=logx+x è di classe 
    C1([a,b]).Proseguendo con le altre ipotesi,si ha:*/
    if((log(a)+a)*(log(b)+b)<0)
    {/*Se f(a)*f(b)<0,si procede con la verifica dell'ultima ipotesi,secondo cui f(x) sia convessa o concava in [a,b].Per farlo,si utilizza la
    derivata prima di f(x),cioè f'(x)=1/x + 1.Questa è monotona decrescente(quindi non crescente)nell'intorno [a,b](preso piccolo) dello zero 
    0.567143 di f(x),quindi è convessa in [a,b].Si prosegue quindi con il calcolo dell'estremo di Fourier x(0).
    Per calcolare quale tra i due punti a e b sia l'estremo x(0) di Fourier dal quale partire con l'approssimazione dello zero di f(x),si deve
    calcolare la derivata seconda f''(x) della funzione,che sarà uguale a f''(x)=-1/x^2.
    Successivamente,per calcolare effettivamente l'estremo di Fourier,si calcola il prodotto tra f(x) e f''(x) nei punti a e b,e si effettua la
    seguente scelta:*/
    if((log(a)+a)*(-1*(-1/pow(a,2)))>0) estremo=a; //se f(a)*f''(a)>0 l'estremo di Fourier x(0) sarà uguale all'estremo a di [a,b]
    else estremo=b; //altrimenti,cioè se f(b)*f''(b)>0,l'estremo di Fourier x(0) sarà uguale all'estremo b di [a,b]
    return estremo;}
    else {printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
          return 1;}
    }
    //Calcolo dell'approssimazione x(i) dello zero di f(x)=logx+x e del numero di iterazioni eseguite,tramite il metodo di Newton:
    int newton(double&estremodifourier,double tau){
    /*Si passa una variabile(l'estremo x(0) )per indirizzo perché la funzione deve restituire due output,cioè la soluzione approssimata e il 
    numero di iterazioni eseguite,e in genere una funzione può restituirne solo uno.*/
    int cont=0;//contatore del numero di iterazioni che si eseguiranno nel metodo di Newton
    double delta;//variabile che servirà per verificare la condizione del criterio di arresto del metodo,cioè |delta|<tau
    double xi=estremodifourier;//dichiarazione di x(i),che all'inizio sarà x(0),cioè l'estremo di Fourier
    double x_imeno1;//dichiarazione di x(i-1) del passo precedente dell'iterazione di Newton
    do{x_imeno1=xi; 
       xi=x_imeno1-((log(x_imeno1)+x_imeno1)/((1/x_imeno1)+1));//x(i)=x(i-1)- f(x(i-1))/f'(x(i-1))
       delta=fabs((xi-x_imeno1));
       cont++;
      }
     while((delta<tau)&&(cont<MAXITERAZIONI));/*condizione di arresto del metodo di Newton:si va avanti finché |x(i)-x(i-1)|<TOLL e finché 
                                              il numero di iterazioni non è al massimo 100*/
    return cont;
    }
    
    Comincia a scrivere le funzioni in maniera più umana, altrimenti perdi tempo con cose che non c'entrano nulla con il problema.

    Non fare calcoli inutili per valutare un segno e controlla il dominio della funzione
    
    double estremodifourier(double, double);
    
    
    double estremodifourier(double a,double b){
        if(a <= 0.0 || b <= 0.0) {
          printf("Dominio della funzione f(x)=logx+x non rispettato\n");
          return NAN;
        }    
        else if((log(a)+a)*(log(b)+b) < 0.0)
            if((log(a)+a) <= 0.0) 
                return a;
            else 
                return b;
        else {
          printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
          return NAN;
        }
    }
    
    
    double x0 = estremodifourier(a,b);
    if (isnan(x0))
        return 0;
    
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Aspetta,il dominio della funzione,o meglio l'intervallo iniziale [a,b],lo deve inserire l'utente...Ora più che altro mi sta venendo un altro dubbio.Nella funzione "newton" in pratica dovrei restituire non uno,ma due valori al main,cioè il numero delle iterate compiute(restituito direttamente,tramite il return) e l'approssimazione "finale" dello zero. Che almeno teoricamente viene calcolata dentro la funzione. Il mio dubbio è questo:ma non è che la funzione per qualche motivo non riesca a prendere in ingresso (per indirizzo)il valore x0(cioè quello che viene fuori da "estremodifourier")? O,sempre per qualche altra ragione che non riesco a vedere,non passa un bel niente al main dopo aver fatto tutto?
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Il dominio lo devi controllare tu dato che passi un parametro alla funzione log.

    Perché tutte queste chiamate per riferimento? Sì ti stanno sfuggendo diverse cose. Prova a scrivere funzioni più semplici, o non usare proprio delle funzioni che il problema non ti chiede quello.
    L'organizzazione del codice in funzioni la puoi fare quando avrai ripassato per bene l'argomento in un programma a parte che non ha problemi matematici nel mezzo
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Allora,l'estremo di Fourier dovrebbe calcolarlo giusto. Però il resto,cioè l'approssimazione e il numero di iterate,lo sbaglia.Il problema sta dentro "newton". Però non ho capito,teoricamente a passare gli passo questo benedetto estremo,in teoria i conti che deve fare sono quelli...Ti riposto il codice completo...
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #define TOLL 1.e-5
    #define MAXITERAZIONI 100
    void letturanumerireali_ab(double&,double&);
    double estremodifourier(double&,double&);
    int newton(double&,double);
    int main(){
    printf("Programma C++ che legge due numeri reali a e b,con a<b(estremi dell'intervallo in cui lo zero di f(x)=logx+x e'stato precedentemente localizzato e separato)e l'estremo di Fourier,cioe' l'approssimazione iniziale dello zero;stampa il numero di iterazioni compiute dal metodo di Newton per approssimare lo zero con errore minore di 10^-5\n(preventivando al massimo 100 iterazioni)e il valore approssimato dello zero fornito dal metodo\n");
    double a,b;
    letturanumerireali_ab(a,b);/*inserimento dei due reali a e b(a<b)estremi dell'intervallo in cui si trova lo zero di f(x):lo zero 
                                semplice di f(x)appartiene ad [a,b]*/
    /*Tramite gnuplot si vede,dal grafico della funzione,che lo zero semplice di f(x)=logx+x(inserita su gnuplot come x-exp(-x)) 
    è circa x=0.567143*/
    double x0=estremodifourier(a,b);//estremo di Fourier dell'intervallo [a,b]
    int iterazioni=newton(x0,TOLL);//metodo di Newton(restituisce,come risultato,il numero di iterazioni eseguite)
    //Dopo la chiamata della funzione newton,il valore x0 sarà diventato quello dell'approssimazione dello zero con il metodo di Newton
    printf("L'approssimazione dello zero di f(x)=logx+x calcolata tramite il metodo di Newton e':%lf\n",x0);
    printf("Il numero di iterazioni eseguite per approssimare lo zero di f(x)=logx+x tramite il metodo di Newton e' %d\n",iterazioni);
    return 0;
    }
    //Inserimento di due numeri reali a e b,con a<b,in cui sarà stato precedentemente localizzato e separato lo zero:
    void letturanumerireali_ab(double& a,double& b){
    printf("Lo zero semplice della funzione f(x)=logx+x(calcolato con gnuplot),appartenente ad [a,b],e' uguale ad x=0.567143\n");
    do{printf("Inserire il numero reale a,tale che a<b:\n");scanf("%lf",&a);
    printf("Inserire il numero reale b,tale che a<b:\n");scanf("%lf",&b);}
    	while(b<=a);
    return;
    }
    //Calcolo dell'estremo di Fourier della funzione nell'intervallo [a,b] (esso rappresenterà l'approssimazione iniziale dello zero di f(x) ):
    double estremodifourier(double& a,double& b)
    {double estremo;
    /*Per calcolare l'estremo di Fourier,devono essere verificate le ipotesi EF,secondo cui in [a,b]: f(x)sia di classe C1([a,b]),f(a)*f(b)<0,e
    f(x) sia convessa,o concava,in [a,b] (cioè f'(x) sia non crescente,o non decrescente,in [a,b]).In questo caso,f(x)=logx+x è di classe 
    C1([a,b]).Proseguendo con le altre ipotesi,si ha:*/
    if((log(a)+a)*(log(b)+b)<0){
    /*Se f(a)*f(b)<0,si procede con la verifica dell'ultima ipotesi,secondo cui f(x) sia convessa o concava in [a,b].Per farlo,si utilizza la
    derivata prima di f(x),cioè f'(x)=1/x + 1.Questa è monotona decrescente(quindi non crescente)nell'intorno [a,b](preso piccolo) dello zero 
    0.567143 di f(x),quindi è convessa in [a,b].Si prosegue quindi con il calcolo dell'estremo di Fourier x(0).
    Per calcolare quale tra i due punti a e b sia l'estremo x(0) di Fourier dal quale partire con l'approssimazione dello zero di f(x),si deve
    calcolare la derivata seconda f''(x) della funzione,che sarà uguale a f''(x)=-1/x^2.
    Successivamente,per calcolare effettivamente l'estremo di Fourier,si calcola il prodotto tra f(x) e f''(x) nei punti a e b,e si effettua la
    seguente scelta:*/
    if((log(a)+a)*(-1*(-1/pow(a,2)))>0) estremo=a; //se f(a)*f''(a)>0 l'estremo di Fourier x(0) sarà uguale all'estremo a di [a,b]
    else estremo=b; //altrimenti,cioè se f(b)*f''(b)>0,l'estremo di Fourier x(0) sarà uguale all'estremo b di [a,b]
    return estremo;}
    else {printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
          return 1;}
     }
    //Calcolo dell'approssimazione x(i) dello zero di f(x)=logx+x e del numero di iterazioni eseguite,tramite il metodo di Newton:
    int newton(double& estremo,double tau){
    /*Si passa una variabile(l'estremo di Fourier x(0) )per indirizzo perché la funzione deve restituire due output,cioè la soluzione
    approssimata e il numero di iterazioni eseguite,e in genere una funzione può restituirne solo uno.*/
    int cont=0;//contatore del numero di iterazioni che si eseguiranno nel metodo di Newton
    double delta;//variabile che servirà per verificare la condizione del criterio di arresto del metodo,cioè |delta|<tau
    double x_imeno1;//dichiarazione di x(i-1) del passo precedente dell'iterazione di Newton
    do{x_imeno1=estremo; 
       estremo=x_imeno1-((log(x_imeno1)+x_imeno1)/((1/x_imeno1)+1));//x(i)=x(i-1)- f(x(i-1))/f'(x(i-1))
       delta=fabs((estremo-x_imeno1));
       cont++;
      }
     while((delta<tau)&&(cont<MAXITERAZIONI));/*condizione di arresto del metodo di Newton:si va avanti finché |x(i)-x(i-1)|<TOLL e finché 
                                              il numero di iterazioni non è al massimo 100*/
    return cont;
    }
    
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    No, non lo calcola giusto, hai sbagliato la derivata seconda. Tra 0.1 e 1 sceglie 1
    Che poi a che ti serve a^2 in una valutazione di un segno?
    I riferimenti non ti servono per calcolare l'estremo, ma ti servono i valori di a e b
    Vabbé se non leggi manco le correzioni oltre a non seguire i consigli, allora in bocca al lupo
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Ma la derivata seconda di logx+x non è -1/(x^2)??? Comunque mi sa che ho sbagliato (tra eventuali altre cose di cui non mi sto rendendo conto) anche la condizione del criterio di arresto. Il procedimento si ferma quando avviene che |x(i)-x(i-1)|<TOLL,giusto? Quindi nel do-while,precisamente nel while finale,dovrei mettere while(|x(i)-x(i-1)|>=TOLL). Ho provato a cambiarla così,ma poi,mentre per alcuni numeri viene proprio la approssimazione corretta,per altre scelte di a e b l'approssimazione viene addirittura NaN Cioè mi dà a prescindere 100 iterate. L'approssimazione dovrebbe andare bene(dovrebbe). Però è strano che faccia sempre 100 iterazioni,obiettivamente.
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    MaximusMeridius ha scritto:


    (-1*(-1/pow(a,2)))
    Ma la derivata seconda di logx+x non è -1/(x^2)???
    Ti sei risposto da solo
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Porca miseria è vero,ho scritto -(- 1/x^2).
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    Ma perché il numero di iterazioni è uguale a 100 a prescindere,se(almeno nelle mie intenzioni)come criterio di arresto ci ho messo,nel while finale,while((delta>tau||delta==tau)||(cont<MAXITERAZIONI)) ?? Questo non me lo spiego davvero
  • Re: Metodo di Newton per calcolare la soluzione approssimata di f(x)=logx+x

    
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #define TOLL 1.e-5
    #define MAXITERAZIONI 100
    void letturanumerireali_ab(double&,double&);
    double estremodifourier(double,double);
    int newton(double&,double);
    int main(){
    printf("Programma C++ che legge due numeri reali a e b,con a<b(estremi dell'intervallo in cui lo zero di f(x)=logx+x e'stato precedentemente localizzato e separato)e l'estremo di Fourier,cioe' l'approssimazione iniziale dello zero;stampa il numero di iterazioni compiute dal metodo di Newton per approssimare lo zero con errore minore di 10^-5\n(preventivando al massimo 100 iterazioni)e il valore approssimato dello zero fornito dal metodo\n");
    double a,b;
    letturanumerireali_ab(a,b);/*inserimento dei due reali a e b(a<b)estremi dell'intervallo in cui si trova lo zero di f(x):lo zero 
                                semplice di f(x)appartiene ad [a,b]*/
    /*Tramite gnuplot si vede,dal grafico della funzione,che lo zero semplice di f(x)=logx+x(inserita su gnuplot come x-exp(-x)) 
    è circa x=0.567143*/
    double x0=estremodifourier(a,b);//estremo di Fourier dell'intervallo [a,b]
    if (isnan(x0))
        return 0;
    int iterazioni=newton(x0,TOLL);//metodo di Newton(restituisce,come risultato,il numero di iterazioni eseguite)
    //Dopo la chiamata della funzione newton,il valore x0 sarà diventato quello dell'approssimazione dello zero con il metodo di Newton
    printf("L'approssimazione dello zero di f(x)=logx+x calcolata tramite il metodo di Newton e':%lf\n",x0);
    printf("Il numero di iterazioni eseguite per approssimare lo zero di f(x)=logx+x tramite il metodo di Newton e' %d\n",iterazioni);
    return 0;
    }
    //Inserimento di due numeri reali a e b,con a<b,in cui sarà stato precedentemente localizzato e separato lo zero:
    void letturanumerireali_ab(double& a,double& b){
    printf("Lo zero semplice della funzione f(x)=logx+x(calcolato con gnuplot),appartenente ad [a,b],e' uguale ad x=0.567143\n");
    do{printf("Inserire il numero reale a,tale che 0<a<b:\n");scanf("%lf",&a);
    printf("Inserire il numero reale b,tale che 0<a<b:\n");scanf("%lf",&b);}
    	while(a <= 0 || b <= 0 || b<=a);
    }
    //Calcolo dell'estremo di Fourier della funzione nell'intervallo [a,b] (esso rappresenterà l'approssimazione iniziale dello zero di f(x) ):
    double estremodifourier(double a,double b)
    {double estremo;
    /*Per calcolare l'estremo di Fourier,devono essere verificate le ipotesi EF,secondo cui in [a,b]: f(x)sia di classe C1([a,b]),f(a)*f(b)<0,e
    f(x) sia convessa,o concava,in [a,b] (cioè f'(x) sia non crescente,o non decrescente,in [a,b]).In questo caso,f(x)=logx+x è di classe 
    C1([a,b]).Proseguendo con le altre ipotesi,si ha:*/
    if((log(a)+a)*(log(b)+b)<0.0){
    /*Se f(a)*f(b)<0,si procede con la verifica dell'ultima ipotesi,secondo cui f(x) sia convessa o concava in [a,b].Per farlo,si utilizza la
    derivata prima di f(x),cioè f'(x)=1/x + 1.Questa è monotona decrescente(quindi non crescente)nell'intorno [a,b](preso piccolo) dello zero 
    0.567143 di f(x),quindi è convessa in [a,b].Si prosegue quindi con il calcolo dell'estremo di Fourier x(0).
    Per calcolare quale tra i due punti a e b sia l'estremo x(0) di Fourier dal quale partire con l'approssimazione dello zero di f(x),si deve
    calcolare la derivata seconda f''(x) della funzione,che sarà uguale a f''(x)=-1/x^2.
    Successivamente,per calcolare effettivamente l'estremo di Fourier,si calcola il prodotto tra f(x) e f''(x) nei punti a e b,e si effettua la
    seguente scelta:*/
    if((log(a)+a)<=0.0) estremo=a; //se f(a)*f''(a)>0 l'estremo di Fourier x(0) sarà uguale all'estremo a di [a,b]
    else estremo=b; //altrimenti,cioè se f(b)*f''(b)>0,l'estremo di Fourier x(0) sarà uguale all'estremo b di [a,b]
    return estremo;}
    else {printf("Non sono verificate le ipotesi dell'Estremo di Fourier per l'applicazione del metodo di Newton alla funzione f(x)=logx+x\n");
          return NAN;}
     }
    //Calcolo dell'approssimazione x(i) dello zero di f(x)=logx+x e del numero di iterazioni eseguite,tramite il metodo di Newton:
    int newton(double& estremo,double tau){
    /*Si passa una variabile(l'estremo di Fourier x(0) )per indirizzo perché la funzione deve restituire due output,cioè la soluzione
    approssimata e il numero di iterazioni eseguite,e in genere una funzione può restituirne solo uno.*/
    int cont=0;//contatore del numero di iterazioni che si eseguiranno nel metodo di Newton
    double delta;//variabile che servirà per verificare la condizione del criterio di arresto del metodo,cioè |delta|<tau
    double x_imeno1;//dichiarazione di x(i-1) del passo precedente dell'iterazione di Newton
    do{x_imeno1=estremo; 
       estremo=x_imeno1-((log(x_imeno1)+x_imeno1)/((1.0/x_imeno1)+1.0));//x(i)=x(i-1)- f(x(i-1))/f'(x(i-1))
       delta=fabs((estremo-x_imeno1));
       cont++;
      }
     while((delta>=tau)&&(cont<MAXITERAZIONI));/*condizione di arresto del metodo di Newton:si va avanti finché |x(i)-x(i-1)|<TOLL e finché 
                                              il numero di iterazioni non è al massimo 100*/
    return cont;
    }
    
Devi accedere o registrarti per scrivere nel forum
14 risposte