Funkcje Przykład: (wartość wielomianu w punkcie) M Dane: liczba naturalna N liczba współczynników wielomianu (= stopień wielomianu +1) tablicaliczbrzeczywistycha 0,a 1,a 2,...,a N 1 współczynnikiwielomianu liczba rzeczywista r punkt, w którym wartość wielomianu nas interesuje Szukane: liczba rzeczywista N 1 i=0 a i r i =a 0 +a 1 r+a 2 r 2 +...+a N 1 r N 1 Funkcje Wykład 6. FUNKCJE, str. 2 Przykład: (wartość wielomianu w punkcie) M #definen6 main(){ double a[n],r,wart; inti; /*wczytanietablicy a orazliczby r */ wart=0.0; for(i=0; i<n; i=i+1) wart = wart + a[i]*potega(r,i); /*wydrukliczby wart */ Jakzrobić,żeby potega(r,i) prawidłowoobliczałar i?
Funkcje Przykład: (definicja funkcji realizującej potęgowanie) M nagłówek ciało wartość wynikowa doublepotega(doubler,inti) { double p; p=1.0; while(i>0) { p=p*r;i=i-1; return p; Nagłówek: typ wynikowy, nazwa, deklaracje parametrów. Ciało: deklaracje lokalne, komendy. Wynik: wyrażenie, którego wartość ma być wartością wywołania. Funkcje Wykład 6. FUNKCJE, str. 4 Fragmenty obliczeń można wyodrębnić w t.zw. funkcje. Definicja funkcji składa się z nagłówka postaci typ nazwa( deklaracje parametrów) (lista parametrów może być pusta), ciała składającego się z deklaracji zmiennych lokalnych oraz instrukcji, nadania wartości. Funkcjestosujesiępoto,żeby: niepisaćwprogramiewielerazytegosamegokodu, rozdzielić problem na mniejsze, logicznie zamknięte fragmenty, móc te fragmenty użyć ponownie, w innym programie.
Funkcje definicja a wywołania Nagłówek definicji funkcji: parametry są zawsze zmiennymi. Wywołanie funkcji w programie: argumenty są wyrażeniami. Liczba i typy argumentów wywołania muszą zgadzać się z liczbą i typami parametrów definicji. Przykład: MNagłówek definicji: double aaa(int n+1) ZŁY parametrmusibyćzmiennąawyrażenien+1niąniejest Nagłówek definicji: double bbb(int n, double x) DOBRY Wywołanie: bbb(5) ZŁE w definicji są dwa parametry a w wywołaniu jeden argument Wywołanie: bbb(5.3*pi,-2) ZŁE pierwszy argument wywołania jest rzeczywisty a zgodnie z definicją miał być całkowity Wywołanie: bbb(-2, 5.3*pi) DOBRE Funkcje definicja a wywołania Wykład 6. FUNKCJE, str. 6 Typwartościfunkcjimożebyćm.in. int, double, char. Funkcja nie może mieć wartości typu tablicowego. Typ wyrażenia nadającego wartość(komenda return) musi być taki sam jak typ funkcji w nagłówku. Funkcję można wywołać tylko w takim miejscu programu, gdzie dopuszczalne jest wyrażenie tego typu. Przykład: MDefinicja: char ccc(int n) {...return 2.0*x; ZŁA typ funkcji(char) nie jest taki sam jak typ nadania wartości(double) Definicja: double ddd(int n) {...return 2.0*x; DOBRA Wywołanie: printf("%c",ddd(2)); ZŁE ddd(2) jest rzeczywiste, nie można go drukować w formacie znakowym Wywołanie: tab[12] = ddd(2*n)/ddd(7); DOBRE
Układ programu z funkcjami Postać definicji funkcji: typ nazwa(listaparametrów){ ciało funkcji return wyrażenie; definicjafunkcji 1 definicjafunkcji 2 definicjafunkcji n main(){ program główny Układ programu z funkcjami Wykład 6. FUNKCJE, str. 8 deklaracje zm. globalnych definicja funkcji 1 definicja funkcji 2 definicja funkcji n main() { deklaracje zm. lokalnych instrukcje zmienne globalne są widoczne w programie głównym i we wszystkich definicjach funkcji o ile nie zostały zasłonięte przez deklaracje lokalne; zmienne lokalne są widoczne tylko w programie głównym; zmienne zadeklarowane w ciele funkcjisąwidocznetylkowtejfunkcji; parametry funkcji również są widoczne tylko w tej funkcji; mainjestjednązfunkcji.
Funkcje zasłanianie zmiennych.......................... deklaracja globalna x; funkcja1(...) { deklaracja lokalna x;...x...; funkcja2(...) { deklaracja lokalna x;...x...; funkcja3(...) { deklaracja lokalna x;...x...; Zmienna, której nazwy użyto w ciele funkcji, pochodzi z deklaracji lokalnej w ciele (lub w nagłówku) tej funkcji. Jeśli zmienna nie posiada deklaracji lokalnej, to pochodzi z deklaracji globalnej na początku programu. Jeśli zmienna nie posiada deklaracji lokalnej ani globalnej, to jest niezadeklarowana; w wielu językach (np. w C) kompilator sygnalizuje wtedy błąd. Funkcje eksponens Wykład 6. FUNKCJE, str. 10 Przykład: MWiadomo z analizy, że e x = + i=0 x i i! Możemy policzyć przybliżoną wartość tej funkcji, urywając obliczenie na jakiejś skończonej liczbie składników: e x n 1 i=0 x i i! Im większe n tym lepsza dokładność.
Funkcje eksponens int silnia(int n){ int i,s; s=1; for(i=2; i<=n; i=i+1) s=s*i; return s; doublepot(doublex,intn){ inti;doublep; p=1.0; for(i=0; i<n; i=i+1) p=p*x; return p; main(){ double x, suma; int n,i; printf("przyblizone e^x\n"); printf("podajx:"); scanf("%lf",&x); printf("ileskladnikow?"); scanf("%i",&n); suma=0.0; for(i=0; i<n; i=i+1) suma = suma + pot(x,i)/silnia(i); printf("\ne^%lf =~=%lf\n\n", x,suma); Uwaga Wykład 6. FUNKCJE, str. 12 Uwaga: Oba podane wyżej programy na wartość wielomianu w punkcie, oraz naprzybliżonąwartośće x zostały napisane bardzo nieoptymalnie.
Oszczędniejszy eksponens suma=0.0;skladnik=1.0; // skladnik= x0 0! for(i=0;i<n;i=i+1) { i 1 x j // suma= & skladnik= xi j=0j! i! suma=suma+skladnik; skladnik=skladnik*x/(i+1); Funkcje organizują program i ułatwiają programiście panowanie nad nim. Ale nieostrożne użycie funkcji może prowadzić do nieoptymalności. Rekursja Wykład 6. FUNKCJE, str. 14
Rekursja double potega(doublea,intn){ if(n==0) return1.0; else return a* potega(a, n-1); main(){ printf("%lf\n",potega(4.0,3)); potega(4.0, 3) = 4.0 potega(4.0, 2) =4.0 4.0 potega(4.0,1) =4.0 4.0 4.0 potega(4.0,0) =4.0 4.0 4.0 1.0 =64.0 Rekursja Wykład 6. FUNKCJE, str. 16 W ciele definicji funkcji może znajdować się wywołanie tej samej funkcji. Definicję zawierającą takie wywołanie nazywa się rekursywną. Wykonanie funkcji zdefiniowanej rekursywnie odbywa się tak, jakby każde wywołanie wewnątrz ciała było zastąpione całym ciałem definicji z parametrami odpowiednio zastąpionymi przez argumenty wywołania. Uwaga: Obliczenie funkcji zdefiniowanej rekursywnie może nigdy się nie skończyć: Przykład: Mdoublepotega(doublea,intn){ if(n==0) return 1.0; else return a*potega(a,n-1); potega(4.0, 1) =4.0 potega(4.0, 2) =4.0 4.0 potega(4.0, 3) =
Rekursja Przykład: (potęga binarna) double potega2(double a, int n) { if(n==0) return 1.0; else if(n%2==0)/*czylinjestparzyste*/ M return potega2(a*a, n/2); else return a* potega2(a, n-1); potega2(2.0, 22) = potega2(4.0, 11) = 4.0 potega2(4.0, 10) =4.0 potega2(16.0,5)=4.0 16.0 potega2(16.0,4) =64.0 potega2(256.0,2)=64.0 potega2(65536.0,1) =64.0 65536.0 potega2(65536.0,0) =4194304 1.0 =4194304 Rekursja Wykład 6. FUNKCJE, str. 18 Przykład: (wieże w Hanoi) M 1 2 3 mamy przełożyć wszystkie krążki z pałeczki 1 na pałeczkę 3, używając pomocniczo pałeczki 2, na raz wolno przełożyć tylko jeden krążek, nigdy nie wolno kłaść krążka większego na mniejszy.
Rekursja Przykład: (wieże w Hanoi) M void Hanoi(intn,inta,intb,intc) { /*nkrążkówzpałeczkianapałeczkęc*/ if(n>0) { Hanoi(n-1, a, c, b); przełóżkrążekzanac; Hanoi(n-1, b, a, c); Rekursja Wykład 6. FUNKCJE, str. 20 Przykład: (wieże w Hanoi) M Hanoi(3,1,2,3) = Hanoi(2,1,3,2); Hanoi(2,2,1,3); = Hanoi(1,1,2,3); 1 2; Hanoi(1,3,1,2); Hanoi(1,2,3,1); 2 3; Hanoi(1,1,2,3); = Hanoi(0,1,3,2); Hanoi(0,2,1,3); 1 2; Hanoi(0,3,2,1); 3 2; Hanoi(0,1,3,2); Hanoi(0,2,1,3); 2 1; Hanoi(0,3,2,1); 2 3; Hanoi(0,1,3,2); Hanoi(0,2,1,3); = 1 2; 3 2; 2 1; 2 3;
Rekursja Przykład: (wieże w Hanoi) MIle ruchów potrzeba, żeby przełożyć n krążków? { R(0)=0 R(n+1)=R(n)+1+R(n) Łatwo sprawdzić przez indukcję, że te dwie równości są spełnione przez funkcję R(n) def =2 n 1 Jeśli ruch trwa sekundę a krążków jest 64, to przekładanie trwa 2 64 sek. 1.8 10 19 sek. 5.85 10 11 lat =585000000000lat (wiekwszechwiata 013750000000lat) Rekursja Wykład 6. FUNKCJE, str. 22 Przykład: (funkcja Ackermanna) M int Ack(intm,intn) { if(m==0) returnn+1; else if(n==0) return Ack(m-1,1); else return Ack(m-1, Ack(m,n-1)); to jest przykład funkcji zdefiniowanej rekursywnie, bardzo szybko rosnącej.
Rekursja Przykład: (funkcja Ackermanna) MAck(0,n)=n+1 Ack(1,0)=Ack(0,1)=2 Ack(1,1)=Ack(0,Ack(1,0))=Ack(0,2)=3 Ack(1,2)=Ack(0,Ack(1,1))=Ack(0,3)=4 Ack(1,n)=n+2 Ack(2,0)=Ack(1,1)=3 Ack(2,1)=Ack(1,Ack(2,0))=Ack(1,3)=5 Ack(2,2)=Ack(1,Ack(2,1))=Ack(1,5)=7 Ack(2,n)=2n+3 Ack(3,0)=Ack(2,1)=5 Ack(3,1)=Ack(2,Ack(3,0))=Ack(2,5)=13 Ack(3,2)=Ack(2,Ack(3,1))=Ack(2,13)=29 Ack(3,n)=2 (n+3) 3 Ack(4,n)=2 2...2 3 n+3dwójki