Domanda Approssimare cos(T*π) con polinomio interpolatore

alessina02

Utente Bronze
2 Gennaio 2022
35
11
0
25
Ultima modifica:
Il codice dovrebbe approssimare f(x)=cos(T*π), con T costante a piacere, prima con il polinomio di Taylor e poi con polinomio interpolatore con i nodi di Chebyshev sull'intervallo [0,π/2].
La function del polinomio dà l'output sbagliato: il problema è che la derivata seconda di cos(x) azzera l'errore e blocca il ciclo while nonostante il risultato sia sbagliato...
Codice:
/*Programma che approssima f(x)=cos(T*pigreco) con il polinomio di Taylor
e quello interpolatore determinato dalla tavola della funzione coseno
relativa agli n0+1 nodi di Chebyshev*/
#include <stdio.h>
#include <math.h>
#define T 1
double leggi_dato (double&);
double funzione (double);//f(x)=cos(T*pi)
double potenza (double, int);
double fattoriale (int);
double modulo (double);
void Taylor (double, double);
double derivate (int, double);
double Lagrange (double, double);
int main()
{double t=leggi_dato (t);
double x=T*M_PI;
printf ("TAYLOR\n");
Taylor (x, t);
printf ("\n\nINTERPOLAZIONE\n");
double l;
l=Lagrange (x, t);
printf ("L'approssimazione vale=%lf", l);
return 0;
}

double leggi_dato (double&a)
{printf ("Inserire tolleranza. t="); scanf("%lf", &a);
return a;}

double funzione (double x)
{x=cos(x);
return x;}


double potenza (double x, int n)
{double p=1;
for (int i=1; i<=n; i++) p=p*x;
return p;}

double fattoriale (int x)
{double fatt=1;
for (int i=2; i<=x; i++) fatt*=i;
return fatt;}

void Taylor (double x, double t)
{int k=0, i=0;
double s=0, y;
do
{y=potenza(x, k)/fattoriale (k);
s+=potenza(-1, i)*y;
k+=2; i++;}
while (modulo(y)>=t);
printf ("L'approssimazione vale=%lf\n", s);
printf ("Il grado del polinomio vale=%d", k);}



double derivate (int n, double x)
{double M;
if (n%4==1) M=cos(x);
else if (n%4==2) M=-sin(x);
else if (n%4==3) M=-cos(x);
else M=sin(x);
return M;}

double Lagrange (double x, double t)
{int n=1;
double l[n+1], a=0, b=M_PI/2, y[n+1], p, w, eps;
do
{for (int i=0; i<=n; i++) {double aux=M_PI*(2*i+1)/(2*n+2);
y[i]=(a+b)/2+(((b-a)/2)*cos(aux));}

for (int i=0; i<=n; i++)
    {l[i]=1; for (int k=0; k<=n; k++)
    {if (k!=i) l[i]*=(x-y[k])/(y[i]-y[k]);}}
p=0;
for (int i=0; i<=n; i++) p+=l[i]*funzione (y[i]);

w=potenza (b-a, n+1)/potenza (2, 2*n+1);
eps= w*derivate(n+1, x)/fattoriale (n+1);
n++;}
while (modulo(eps)>=t);
return p;}

double modulo (double a)
{if (a<0) return -a;
else return a;}
 
Ultima modifica:
Il codice dovrebbe approssimare f(x)=cos(T*π), con T costante a piacere, prima con il polinomio di Taylor e poi con polinomio interpolatore con i nodi di Chebyshev sull'intervallo [0,π/2].
La function del polinomio dà l'output sbagliato: il problema è che la derivata seconda di cos(x) azzera l'errore e blocca il ciclo while nonostante il risultato sia sbagliato...
Codice:
/*Programma che approssima f(x)=cos(T*pigreco) con il polinomio di Taylor
e quello interpolatore determinato dalla tavola della funzione coseno
relativa agli n0+1 nodi di Chebyshev*/
#include <stdio.h>
#include <math.h>
#define T 1
double leggi_dato (double&);
double funzione (double);//f(x)=cos(T*pi)
double potenza (double, int);
double fattoriale (int);
double modulo (double);
void Taylor (double, double);
double derivate (int, double);
double Lagrange (double, double);
int main()
{double t=leggi_dato (t);
double x=T*M_PI;
printf ("TAYLOR\n");
Taylor (x, t);
printf ("\n\nINTERPOLAZIONE\n");
double l;
l=Lagrange (x, t);
printf ("L'approssimazione vale=%lf", l);
return 0;
}

double leggi_dato (double&a)
{printf ("Inserire tolleranza. t="); scanf("%lf", &a);
return a;}

double funzione (double x)
{x=cos(x);
return x;}


double potenza (double x, int n)
{double p=1;
for (int i=1; i<=n; i++) p=p*x;
return p;}

double fattoriale (int x)
{double fatt=1;
for (int i=2; i<=x; i++) fatt*=i;
return fatt;}

void Taylor (double x, double t)
{int k=0, i=0;
double s=0, y;
do
{y=potenza(x, k)/fattoriale (k);
s+=potenza(-1, i)*y;
k+=2; i++;}
while (modulo(y)>=t);
printf ("L'approssimazione vale=%lf\n", s);
printf ("Il grado del polinomio vale=%d", k);}



double derivate (int n, double x)
{double M;
if (n%4==1) M=cos(x);
else if (n%4==2) M=-sin(x);
else if (n%4==3) M=-cos(x);
else M=sin(x);
return M;}

double Lagrange (double x, double t)
{int n=1;
double l[n+1], a=0, b=M_PI/2, y[n+1], p, w, eps;
do
{for (int i=0; i<=n; i++) {double aux=M_PI*(2*i+1)/(2*n+2);
y[i]=(a+b)/2+(((b-a)/2)*cos(aux));}

for (int i=0; i<=n; i++)
    {l[i]=1; for (int k=0; k<=n; k++)
    {if (k!=i) l[i]*=(x-y[k])/(y[i]-y[k]);}}
p=0;
for (int i=0; i<=n; i++) p+=l[i]*funzione (y[i]);

w=potenza (b-a, n+1)/potenza (2, 2*n+1);
eps= w*derivate(n+1, x)/fattoriale (n+1);
n++;}
while (modulo(eps)>=t);
return p;}

double modulo (double a)
{if (a<0) return -a;
else return a;}
allora, non ci sono errori gravi, ma per cortesia rende il codice un po' più ordinato, perché alcune cose sono davvero indentate male, non per altro, se un'altra persona deve leggere il codice diventa inutilmente più difficile. in primo luogo il compilatore di da qualche avviso? Allora adesso prova a copiare il codice e a risistemarlo. Comunque scusa per il tono non è aggressivo, semplicemente l'ordine rende più semplice la correzione degli errori e anche il confronto