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;
}