[C] Funzione coseno

bad.alex
Ragazzi, avrei bisogno del vostro aiuto.

Ho svolto soltanto il primo punto del seguente esercizio ( in apparenza non difficilissimo!):
"Si consideri il seguente sviluppo in serie di Taylor della funzione coseno, approssimato al termine kesimo,
con k scelto dall'utente tramite tastiera:
cos x=$Σ(-1)^n/(2n!)x^(2n)$
1. scrivere una funzione C che implementa la serie di Taylor suindicata; (Svolto)
2. calcolare, per ogni x appartenente all'intervallo [a, b], con incrementi di 0.01, con a e b forniti da
tastiera (da esprimere in radianti) i valori del coseno restituiti dalla serie di Taylor; ( non capisco cosa debba essere incrementato)
3. memorizzare su un vettore “risultati”, allocato dinamicamente e la cui dimensione dovra' essere
opportunamente determinata, il risultato della funzione cos(x), presente nella libreria math.h,
quello fornito dalla serie di Taylor e la loro differenza; a tale scopo utilizzare un array di
strutture i cui campi dovranno essere opportunamente scelti. ( qui occorre il vostro aiuto)"

Il codice che ho scritto e':

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


double potenza (double, int);
double fattoriale ( int);
double coseno ( double, int);
double cos_gra ( double base, int approx, float a, float b);

int main (void) {
    double x, cos,a,b,ag,bg, cos_g, *risultati, value;
    int esp, k, dim, i;
    
    printf ("Inserire da tastiera il valore x \n");
    scanf ("%lf", &x);
    printf ("Inserire il valore esp \n");
    scanf ("%d", &esp);
    printf ("Calcolo la potenza di x \n");
    
potenza (x,esp); 
printf (" %lf", potenza(x,esp));

    printf (" Digita il termine di approssimazione \n");
    scanf( "%d", &k);
    
    printf ("Calcolo il coseno di x \n");
    
    cos= coseno (x,k);
    printf ("Il coseno di %lf e' %lf \n", x, coseno(x,k));
    
    printf (" Inserire da tastiera il valore di a in radianti \n");
    scanf (" %lf", &a);
    printf (" Inserire da tastiera il valore di b in radianti \n");
    scanf (" %lf", &b);
    
    ag = (a*180)/3.14;
    bg = (b*180)/3.14;
    
    printf (" Il valore di a in gradi e' %lf \n", ag);
    printf (" Il valore di b in gradi e' %lf \n", bg);
                        
   if ((x>=ag)&&(x<=bg)) {
          cos_g =  cos_gra ( x, k, a, b);
          }
          printf (" Il coseno e' %lf \n", cos_g);
          
   
        
    system("pause");
}


double potenza ( double base, int esponente){
       
       int i;
       double pot;
       
       if(esponente<0) esponente=-esponente;
       else esponente=esponente;
       
       pot=1;
       for(i=0; i<esponente; i++){
                pot=pot*base;
                }
                if(esponente<0) return (1/pot);
                else return(pot);
                }
                
double fattoriale (int n){
       
       double fatt;
       int i;
       
       fatt=1;
       for(i=1; i<=n; i++){
                fatt=fatt*i;
                }
                return (fatt);
                }

double coseno ( double base, int approx) {
       int i;
       double serie;
       
       serie = 0;
       for (i=0; i< approx; i++) {
           serie=serie+(potenza(-1, i)*potenza(base, 2*i))/fattoriale(2*i);
                }
                return(serie);
                }
                
double cos_gra ( double base, int approx, float a, float b) {
       int i;
       double serie;
       
       serie =0;
       for (i=0; i<approx; i=i+0.01) {
           serie = serie + (potenza (-1, i)*potenza(base, 2*i))/fattoriale (2*i);
        
           }
return (serie);
}


Ci deve essere almeno un errore nel secondo punto, quando mi si chiede di incrementare qualcosa.
Per il terzo punto avrei bisogno che mi spiegate com procedere.
Vi ringrazio

Risposte
vict85
Prima di passare alla parte dinamica vorrei farti notare che il tuo algoritmo andrebbe migliorato*.

Vediamo il perché:
[list=1][*:2aybdg4p] Stai ricalcolando il fattoriale tutte le volte quando ti basta moltiplicare per n l'ultimo fattoriale calcolato.[/*:m:2aybdg4p]
[*:2aybdg4p] Stessa cosa per la potenza. Questo e quello precedenti possono essere uniti moltiplicando il tutto per \(\displaystyle x^2/n \).[/*:m:2aybdg4p]
[*:2aybdg4p] Non prendi in considerazione un metodo di blocco differente dal numero di ripetizioni.[/*:m:2aybdg4p]
[*:2aybdg4p] Il metodo di Taylor è locale, significa che poco preciso lontano da 0. In genere infatti si preferisce usare polinomi di interpolazione quando si vuole approssimare qualcosa su un intervallo. Inoltre il coseno è simmetrico. Dovresti quindi assicurarti che il risultato sia incluso nel \(\displaystyle [0,1/2\pi] \) e in caso contrario portarcelo.[/*:m:2aybdg4p][/list:o:2aybdg4p]


* anche se gradirei che ogni tanto qualche professore si rendesse conto che taylor è un bruttissimo algoritmo per l'approssimazione di seni e coseni. Infatti math.h NON lo usa e neanche il processore (forse non lo sai ma intel e amd ti forniscono una superefficiente e molto precisa implementazione hardware di cos, sin e similari). È molto probabile che math.h chiami l'istruzione del processore. Ci sono comunque metodi software migliori sotto tutti i punti di vista.

bad.alex
Ti ringrazio Vict. Quei procedimenti sono quelli imparati durante le lezioni, standard.
Dovrebbero comunque far funzionare il programma. Il problema nasce nel secondo punto, al momento dell'incremento perchè mi sono perso nei calcoli...

apatriarca
Suppongo che tu debba considerare i valori \( a, a+0.01, a+0.02, .. , b. \)

bad.alex
grazie apatriarca. Provo in questo modo :)

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.