Pętla for w Octave Roman Putanowicz 13 kwietnia 2008 1 Zakresy i operator “:” Zakresy (ang. ranges) są wygodnym sposobem definiowania wektorów reprezentujących ciągi arytmetyczne, czyli ciągi w których różnica pomiędzy dwoma kolejnymi elementami jest stała. Wyrażenie będące zakresem określone jest przez podanie wartości początkowej ciągu, opcjonalnie przyrostu elementów ciągu oraz maksymalnej wartości (tzw. kresu górnego), której nie mogą przekroczyć elementy ciągu. Wartość początkową, przyrost i kres górny podaje się odesparowane dwukropkiem ’:’. wartość początkowa : przyrost : kres górny Jeżeli przyrost nie zostanie podany domyślnie przyjmowana jest wartość 1. Przykłady: octave:1> 1:2:9 ans = 1 3 5 7 9 octave:2> 1:7 ans = 1 2 3 4 5 6 7 Podanie negatywnej wartości przyrostu wraz z odpowiednią wartością kresu górnego pozwala na definiowanie ciągu o wartościach malejących: octave:3> 10:-1:0 ans = 10 9 8 7 6 5 4 3 2 1 0 Wszystkie trzy wielkości definiujące zakres, to jest wartość początkowa, przyrost i kres górny mogą być wartościami rzeczywistymi: octave:4> 1.5:0.3:3.7 ans = 1.5000 1.8000 2.1000 2.4000 2.7000 3.0000 3.3000 3.6000 Uwaga: w przypadku użycia w definicji zakresu wartości rzeczywistych kres górny może nie być uwzględniany w wyniku, nawet jeżeli przyrost mieści się całkowitą liczbę razy w przedziale wyznaczonym przez wartość początkową i kres górny (np. 1:0.2:3). Dzieje się tak na skutek błędów zaokrągleń przy operowaniu liczbami rzeczywistymi. Jeżeli konieczna jest gwarancja by wartości skrajne zakresu były uwzględnione w wyniku, należy skorzystać z funkcji linspace. Zakresy są interpretowane jako wektory wierszowe, z tym, że jeżeli nie ma potrzeby Octave nie skonwertuje zakresu do wektora, oszczędzając tym samym na pamięci potrzebnej na przechowywanie elementów wektora. octave:5> a = 1:4 a = 1 2 3 4 octave:6> isvector(a) ans = 1 octave:7> size(a) ans = 1 4 1 Każda z wielkości definiujących zakres może być podana jako dowolne wyrażenie arytmetyczne lub wywołanie funkcji: octave:8> i=2; octave:9> 1-0.5 : sin(0.9) : i^2 ans = 0.50000 1.28333 2.06665 2.84998 3.63331 2 Instrukcja for Instrukcja for ma następującą składnię: for zmienna = wyrażenie instrukcje endfor gdzie: instrukcje oznacza jedną lub więcej instrukcji, zmienna oznacza nazwę zmiennej a wyrażenie oznacza jakiekolwiek poprawne wyrażenie. Instrukcja for działa w ten sposób, że zmiennej przypisywane są kolejne kolumny wyrażenia. Jeżeli wynikiem wyrażenia jest wektor wierszowy to zmienna będzie skalarem i będzie przyjmowała kolejne wartości elementów wektora. Po przypisaniu zmiennej kolejnej wartości wykonywane są instrukcje. Przykłady: octave:10> for i=1:4 > disp(i); > endfor 1 2 3 4 octave:11> for i=[7,3,2,8] > disp(i); > endfor 7 3 2 8 octave:12> v = [1,3,4,5] v = 1 3 4 5 octave:13> for i = v > disp(i); > endfor 1 3 4 5 2.1 Przykłady Wypisywanie kolejnych liczb nieparzystych Napisz skrypt, który będzie wypisywał N kolejnych liczb nieparzystych, przy czym wartość N podaje użytkownik. Zadanie to można rozwiązać na dwa sposoby: Sposób 1 – policzyć jaka ma być maksymalna liczba nieparzysta, którą trzeba wypisać i skorzystać z instrukcji zakresu tak by od razu generowała żądany ciąg: N = input("Podaj ilosc liczb nieparzystych : "); maxnp = 2*N-1; for i=1:2:maxnp disp(i); endfor Powyższy skrypt zapisujemy w pliku o nazwie np.m a następnie uruchamiamy poleceniem: octave -q np.m 2 Sposób 2 – wykorzystać związek między indeksem (kolejnym numerem) liczby nieparzystej a jej wartością: N = input("Podaj ilosc liczb nieparzystych : "); for i=1:N v = 2*i - 1; disp(v); endfor Wypisywanie kolejnych elementów ciągu arytmetycznego Ciąg arytmetyczny to taki ciąg, w którym różnica dwu kolejnych argumentów jest stała. Przy tym założeniu można wyprowadzić wzór: ai = a0 + i ∗ r gdzie a0 jest wyrazem początkowym, i indeksem elementu, a r różnicą ciągu. n = input("Podaj r = input("Podaj a = input("Podaj for i=0:n-1 v = a = i*r; printf("a_%d = endfor ilość elementów ciągu : ") różnicę ciagu : ") element początkowy : ") %g\n", i, v); Powyższy skrypt zapisujemy w pliku o nazwie artymet.m i uruchamiamy poleceniem: octave -q arytmet.m Wypisywanie elementów wektora większych niż określona wartość Napisz skrypt, który poprosi użytkownika o podanie wektora oraz wartości granicznej, a następnie wypisze tylko te elementy wektora, które są większe niż wartość graniczna. v = input("Podaj wektor (np: [1,3,4]) : "); g = input("Podaj wartosc graniczna : "); printf("Elementy wektora wieksze niz %g\n", g); n = length(v); for i = 1:n if (v(i) > g) printf("v_%d : %g\n", i, v(i)); endif endfor 3 Podstawowe algorytmy W tym punkcie zostaną omówione dwa podstawowe algorytmy: algorytm przeglądnięcia elementów ciągu i akumulacji rezultatów operacji na przeglądanych elementach oraz algorytm znajdowania maksymalnego (minimalnego) elementu ciągu. 3.1 Notacja Σ i Π W celu zwartego zapisywania wyrażeń będących sumą kolejnych elementów ciągu wprowadza się notację Σ: n X i = 0 + 1 + 2 + . . . + (n − 1) + n i=0 3 Przykłady: 3 X (i + 1)2 = (0 + 1)2 + (1 + 1)2 + (2 + 1)2 + (3 + 1)2 2 X (m + i) = (m + 0) + (m + 1) + (m + 2) 3 X a·i = a·1+a·2+a·3 =a i=0 i=0 3 X iprzy założeniu, że a =const i=1 i=1 Na podobnej zasadzie działa notacja Π. Oznacza ona iloczyn kolejnych elementów ciągu: n Y i = 1 · 2 · . . . · (n − 1) · n 3 Y i= 1·2·3= 6 i=1 Przykłady: i=1 3 Y i2 = 1 2 · 2 2 · 3 2 = 1 · 4 · 9 i=1 Nietrudno zauważyć następujący związek: n Y i = n! i=1 3.2 Implementacja wyrażeń zawierających P P Chcąc w programie komputerowym obliczyć wyrażenie zawierające musimy skonstruować algorytm, który będzie akumulował (gromadził) wartości kolejnych elementów sumy. Trzy podstawowe elementy tego algorytmu to: • przypisanie wartości 0 do zmiennej, która będzie reprezentować sumę (zero dlatego, że nie dodaliśmy jeszcze żadnego elementu), • wygenerowanie kolejnych elementów sumy, • uaktualnienie sumy przez dodanie do starej wartości sumy nowego elementu. Pn Poniżej zamieszczono przykład programu, który oblicza wartość wyrażenia i=1 i2 dla n podanego przez użytkownika n = input("Podaj n : "); suma = 0; for i = 1:n suma = suma + i^2; endfor printf("Wartosc sumy : %g\n", suma); 3.3 Implementacja wyrażeń zawierających Implementacja wyrażeń zawierających Q Q jest analogiczna do tej dla P : • Inicjalizacja zmiennej, która będzie reprezentować iloczyn wartością 1 (jeden dlatego, że jest to wartość neutralna dla mnożenia, tak jak 0 jest wartością neutralną dla dodawania). • Wygenerowanie kolejnych elementów iloczynu • Uaktualnienie iloczynu przez pomnożenia starej wartości iloczynu przez kolejny element. Qn Poniżej zamieszczono przykład programu, który oblicza n! = i=1 i 4 n = input("Podaj n : "); iloczyn = 1; for i = 1:n iloczyn = iloczyn * i; endfor printf("Wartosc n! : %g\n", iloczyn); 3.4 Znajdowanie maksymalnego elementu ciagu Algorytm znajdowania maksymalnego elementu ciągu składa się z następujących kroków: 1. przyjmij pierwszy element ciągu jako element maksymalny, 2. przeglądaj następne elementy – jeżeli któryś z nich jest większy niż przyjęty element maksymalny to zastąp nim element maksymalny. Poniżej zamieszczono przykład programu znajdującego maksymalny element w wektorze (w Octave używamy wektorów do reprezentowania ciągów o skończonej liczbie elementów) v = input("Podaj wektor : "); n = length(v); max = v(1); for i = 2:n if max < v(i) max = v(i); endif endfor printf("Maksymalny element wektora to : %g\n", max); 4 Zadania różne Poniżej przedstawiono przykłady różnych zadań wymagających użycia pętli. Obliczanie iloczynu skalarnego wektorów Napisz skrypt, który obliczy iloczyn skalarny wektorów nie korzystając z operatora “*” w odniesieniu do wektorów. Iloczyn skalarny można wyrazić przez współrzędne jako: X vi · ui v◦u= i Skrypt realizujący powyższe obliczenia: v = input("Podaj wektor v : "); u = input("Podaj wektor u : "); n = length(v); s = 0; for i = 1:n s = s + v(i) * u(i); endfor printf("Skalarnie v*u = %g\n", s); Rysowanie wielokąta foremnego Napisz skrypt, który narysuje N -kąt foremny wpisany w okrąg o promieniu R. Patrząc na rysunek można łatwo zauważyć, że współrzędne N-kąta foremnego dane są wzorem: 2π · (i − 1) ) N 2π · (i − 1) ) yi = R · sin( N xi = R · cos( gdzie i = 1, . . . , N . 5 y 2 3 β 4 1 x 6 5 N = input("Podaj ilosc bokow n=") R = input("Podaj promien okregu R=") beta = 2*pi/N; for i = 1:N+1 x(i) = R * cos(beta * (i-1)); y(i) = R * sin(beta * (i-1)); endfor axis("square"); plot(x,y, "@-"); pause() 5 Ćwiczenia 1. Napisz skrypt, który będzie wypisywał wszystkie liczby nieparzyste w przedziale [2, 49] ale od największej do najmniejszej. 2. Napisz skrypt, który wypisze sześciany N początkowych liczb nieparzystych. N podaje użytkownik. 3. Napisz skrypt, który dla podanego przez użytkownika wektora wypisze tylko te elementy, które są ujemne. 4. Napisz skrypt, który dla podanego przez użytkownika wektora obliczy sumę elementów ujemnych. 5. Napisz skrypt, który obliczy długość euklidesową dowolnego n-wymiarowego wektora. Długość ta dana jest wzorem: q ||v|| = v12 + v22 + . . . + vn2 6. Napisz skrypt, który znajdzie indeks minimalnego elementu wektora. 6