Sunteți pe pagina 1din 9

Seminar 2 - Atp Pointeri spre functii I.

Teorie despre pointeri la functii


In C, numele unei functii este un pointer care indica adresa de memorie unde incepe codul executabil al functiei. Aceasta permite transmiterea functiilor ca parametri in subprograme precum si lucrul cu tabele de functii. Pentru acest scop, se parcurg etapele: a) declararea unei variabile de tip procedural (pointer spre functie) tip_rezultat (*nume_var)(lista_parametri_formali); unde: nume_var este o variabila de tip procedural si are tipul pointer spre functie cu parametrii lista_parametri_formali si care returneaza o valoare de tipul tip_rezultat. Lui nume_var i se poate atribui ca valoare doar numele unei functii de prototip corespunzator acestui tip: tip_rezultat nume_f(lista_parametri_formali);

b) descrierea functiei care utilizeaza parametrul procedural: void f(, tip_rezultat (*nume)(lista_parametrilor_formali), ) { tip_rezultat x; x=(*nume)(lista_parametrilor_actuali); } unde nume este parametrul formal de tip procedural. c) apelul functiei cu parametri procedurali: tip_rezultat nume_functie(lista_parametri_formali) { } void main () { f(, nume_functie, ); }

Atentie: a nu se confunda:
un pointer la o functie: tip_returnat (*pointer_f) ([parametri] ) cu o functie care are ca rezultat un pointer: tip_returnat *pointer_f ([parametri])

II. Exemple
1. Exemplu cu vectori
Enunt - Fie o functie care efectueaza o prelucrare asupra unui vector. Nu se cunoaste apriori tipul prelucrarii, aceasta fiind descrisa de o alta functie primita ca parametru. Pot exista mai multe functii care descriu prelucrari diferite asupra unui vector si oricare din ele poate fi transmisa ca paramteru. Tipul prelucrarii va consta in: - suma elementelor unui vector - media elementelor vectorului Exemplu numeric Numarul de elemente(<10):5 a[0]=1 a[1]=2 a[2]=3 a[3]=4 a[4]=5 Suma elementelor: Rezultatul prelucrarii este: 15.00 Media elementelor: Rezultatul prelucrarii este: 3.00 Indicatii 1. Se includ bibliotecile: stdio.h, conio.h 2. Se scriu functiile de prelucrare: - Suma elementelor unui vector: float suma(float *v, int n) {int i; float s=0; return (s);} - Media elementelor vectorului float media (float *v, int n) {int i; float m=0; return (m);} 3. Functia functie foloseste parametrul procedural //pct. b - descriere functiei ce fol parametrul procedural float functie (float vec[], int dim, float (*prelucrare)(float*, int)) {

float x; x= (*prelucrare)(vec,dim); return x; //sau return (*prelucrare)(vec,dim); } 4.In functia main: - se declara de tip intreg: i,m - se declara de tip float: vector[10] - se citeste m de la tastatura, numarul de elemente pentru vector (maxim 10) - se citesc de la tastatura elementele vectorului vector, elemente de tip float - se apeleaza functia functie (afisand totodata si rezultatul pentru suma): printf("Rezultatul prelucrarii este: %5.2f\n", functie(vector,m,suma)); - se apeleaza functia functie (afisand totodata si rezultatul pentru medie): printf("Rezultatul prelucrarii este: %5.2f\n", functie (vector,m,media));

2.Exemplu metoda bisectiei


Pentru calculul rdcinilor reale ale unei ecuaii algebrice se utilizeaz mai multe metode numerice dintre care amintim: metoda biseciei (bipartiiei), metoda aproximaiilor succesive, metoda lui Newton Raphson, metoda lui Lobacevski. - enunt:

- descriere metoda (I. Rusu Metode numerice, 2006)

- exemplu numeric pentru functia f(x)= x*x*x-3*x+14. Pentru solutia gasita mai jos f(-2.822266) este aprox. -0.013072 Introduceti limitele intervalului: -10 10 Eroarea admisa: 0.01 Numarul de iteratii: 1000 Solutia aproximativa este: -2.822266

Indicatii program 1. Biblioteci - stdio.h, conio.h, math.h 2. Prototipuri functii (bisectie si functie pentru care se aplica metoda bisectiei) //prototipul functiei bisectie void bisectie (float, float, float (*f)(float), float, long, int*, float *); /*prototipul functiei pentru care se aplica metoda bisectiei*/ float fct (float); 3. In functia main: - Se declara: float a,b,eps,x; int cod; long n; float (*functie)(float); - Se citesc de la tastatura: limitele intervalului (a si b), eroarea admisa (eps), numarul de iteratii (n, ex: scanf ("%li", &n);) - Variabila functie primeste valoare functiei fct de analizat. functie=fct; Se apeleaza functia bisectie: bisectie (a, b, functie, eps, n, &cod, &x); Se testeaza valoarea variabilei cod: if(!cod) printf ("\n Nu se poate calcula solutia aproximativa"); else printf("\n Solutia aproximativa este: %f", x);

4. descriere functie pentru care se aplica met. bisectiei*/ float fct(float x) { return x*x*x-3*x+14; } 5. functia care implementeaza metoda bisectiei:

void bisectie(float a, float b, float (*f)(float), float eps, long n, int *cod, float *x) {int gata=0; long c; for (c=0;(c<n)&&!gata; c++) { *x=(a+b)/2; gata= fabs(*x-a)<eps; if((*f)(*x)*(*f)(a)<0) b=*x; else a=*x; } *cod=gata; }

Exercitii pentru acasa


1. S se scrie funcia pentru aproximarea valorii soluiei unei ecuaii algebrice transcendente prin metoda tangentei. Indicatii:
Una dintre cele mai cunoscute si mai folosite tehnici de rezolvare a ecuatiilor neliniare este metoda Newton, denumita uneori si metoda Newton-Raphson sau metoda tangentelor. Ea se deosebeste de alte metode de aproximatii succesive prin faptul ca pentru fiecare punct din sirul aproximatiilor este necesara atat evaluarea functiei f(x) ce defineste ecuatia, cat si a derivatei acesteia f '(x).

Valoarea aproximativa a radacinii exacte se calculeaza folosind un sir de aproximatii succesive {x_0, x_1, x_2, ... } construit dupa urmatorul model. Pornind de la aproximatia x_0, curba y=f(x) este aproximata in punctul de coordonate (x_0, f(x_0)) prin tangenta la ea. Noua aproximatie x_1 se obtine la intersectia acestei tangente cu axa absciselor.

Folosind pe x_1 ca aproximatie initiala, se reia procedeul, determinandu-se o noua aproximatie x_2 s.a.m.d. pana cand abaterea intre doua iteratii succesive scade sub o valoare prag impusa: |x_(n+1) - x_n| < .

Alegerea aproximatiei initiale influenteaza in buna masura procesul iterativ. (a) Daca aproximatia initiala este prea departe de solutia exacta, este posibil ca, datorita unei forme aparte a curbei y = f(x), noile aproximatii sa fie aruncate spre infinit. (b) Intr-o situatie mai fericita, procesul ramane convergent, dar sirul aproximatiilor succesive se indreapta catre o alta radacina decat cea cautata. Conditiile de convergenta ale metodei Newton sunt relativ complexe ca forma si se refera nu numai la functia f(x), ci si la primele sale doua derivate, f '(x) si f ''(x).

METODA NEWTON-RAPHSON Condiia de convergen a irului, spre soluia ecuaiei, este dat de relaia Pentru convergena metodei Newton - Raphson este necesar ca Formula Newton - Raphson poate fi scris i pentru ecuaia implicit astfel : .

Formula mai poart numele i de metoda tangentei. n acest caz:

iar condiiile de convergen se transcriu: 1. Soluia de start s fie ct mai aproape de soluia ecuaiei, f(x)s fie ct mai mic; 2. f''(x) s fie ct mai mic; 3. f' (x) s fie ct mai deprtat de zero.

Funcia are ca parametri de intrare soluia iniial (x0), numrul maxim de iteraii (n), precizia cerut (eps), valoarea minim a tangentei (eps2), funcia asociat ecuaiei (f), derivata funciei asociate ecuaiei (fd), derivata funciei de iteraie (gd) i adresa unde se va nscrie soluia. Funcia returneaz prin numele su un cod cu urmtoarea semnificaie: 0 nu s-a gsit soluie datorit numrului prea mic de iteraii; 1 nu s-a gsit soluie datorit anulrii derivatei funciei asociate ecuaiei; 2 nu s-a gsit soluie deoarece metoda nu este convergent pentru datele primite; 3 s-a gsit soluie aproximativ. int tangenta(float x0, int n, float eps, float eps2, float (*f)(float), float (*fd)(float), float(*gd)(float), float *x) { int cod=0; while((n) && (!cod)) {if(fabs((*fd)(x0))<eps2) cod=1; else if(fabs((*gd)(x0))>1) cod=2; else {*x=x0-(*f)(x0)/(*fd)(x0); if(fabs(*x-x0)<eps1) cod=3; else {x0=*x; n--;} } } return cod;}

2. Scrieti un program care aproximeaza valoarea integralei ( ) prin metoda trapezului. Indicatie: Pentru rezolvare se determina o diviziune a intervalului [a,b]. Considerand punctele determinate de punctele diviziunii si valorile functiei f in acestea, se obtine o serie de trapeze dreptunghiulare alaturate. Suma ariilor acestor trapeze aproximeaza suprafata dintre graficul functiei si axa reala, deci valoarea integralei. Aria unui trapez dreptunghic este jumatate din produsul dintre inaltinmea trapezului si suma bazelor.

O posibila forma a a functiei este urmatoarea: double integrala_aprox (double a. double b, double (*f)(double), int n) { double rez, s; int i; double st, dr, l; l=(b-a)/n; rez=0; for (i=0;i<n;i++) rez= rez+(*f)(a+i*l); rez= rez+(*f)(a)/2+(*f)(b)/2; rez*=l; return rez; }

Apel: double int_a_b; int n; double a,b; Int_a_b = integrala_aprox(a,b,f,n);

S-ar putea să vă placă și