Octave rzadko kiedy bywa używany jak zwykły kalkulator do wyznaczania wartości gotowych wyrażeń matematycznych. Jego prawdziwa siła objawia się bowiem dopiero wtedy, gdy potraktujemy go jak język programowania, w którym przygotowuje się wielolinijkowe skrypty. Takie skrypty z reguły zawierają zmienne i funkcje definiowane przez użytkownika.
Definiowanie zmiennych jest banalnie proste: piszemy jej nazwę, znak =
,
a po nim wartość zmiennej, np.:
> a = 1 a = 1
Dużo ciekawsza jest kwestia rodzaju zmiennych, jakich możemy używać w Octave. W niniejszym kursie skoncentrujemy się na najbardziej użytecznych typach danych:
who -l variables
123
, -3.14
, 1.2e-10
.
Niezależnie od zapisu, skalary reprezentowane są przez Octave jako tzw.
liczby zmiennopozycyjne
podwójnej precyzji (IEEE-754 double).
Uwaga: Octave umożliwia też deklarowanie skalarów innych typów, np.
całkowitych (8, 16, 32 i 64 bitowych), zmiennopozycyjnych w pojedynczej precyzji oraz
zespolonych. Przykłady skalarów zespolonych:
i
, 1 + 3i
, 1.2 - 3.4i
.
> a = [1, 2, 3, 4] a = 1 2 3 4Uwaga: przecinki można pominąć, ale może prowadzić to do subtelnych błędów podczas interpretacji wyrażeń.
Dostęp do wartości n-ego elementu wektora a
zapewnia wyrażenie a(n)
:
> a(2)=3 a = 1 3 3 4Jak widać, pierwszy element wektora n-elementowego to
a(1)
, a element ostatni
to a(n)
.
Wektory można łatwo rozszerzać o nowe elementy:
> a = [a, 7, [10,100]] a = 1 3 3 4 7 10 100Liczbę elementów wektora można zbadać funkcją
length
> length(a) ans = 7W powyższych przykładach mieliśmy do czynienia z tzw. wektorami wierszowymi. Octave rozpoznaje też wektory kolumnowe. Kolejne elementy wektorów kolumnach oddziela się od siebie średnikami:
> v = [1; 2; 5] v = 1 2 5
m
jako wektora kolumnowego o dwóch elementach, z których każdy jest
dwuelementowym wektorem wierszowym:
> m = [[1, 2]; [3, 4]] m = 1 2 3 4
Takie uogólnione wektory nazywamy macierzami.
Macierz o n
wierszach
i m
kolumnach zwie się "macierzą n
na m
".
Jeżeli m
= n
, macierz zwie się kwadratową. W powyższym przykładzie m
jest więc macierzą kwadratową o dwóch wierszach i dwóch kolumnach, czyli "2 na 2".
Macierze można też interpretować jako wektory wierszowe, których elementy są wektorami kolumnowymi:
m = [[1; 3], [2; 4]] m = 1 2 3 4Zapis macierzy zwykle upraszcza się jeszcze bardziej, po prostu podając wartości elementów w kolejnych wierszach i kolumnach:
m = [1, 2; 3, 4] m = 1 2 3 4Liczbę wierszy dowolnej macierzy zwraca funkcja
rows
, liczbę kolumn zwraca funkcja columns
, a funkcja size
zwraca
liczbę wierszy i kolumn jako wektor "1 na 2":
> rows(m) ans = 2 > columns(m) ans = 2 > size(m) ans = 2 2
Uwaga! Dla Octave skalary i wektory to pewne specjalne rodzaje macierzy: skalary to macierze
"1 na 1", wektory wierszowe to macierze "1 na n
", a wektory kolumnowe to
macierze "n
na 1".
Aby uzyskać dostęp do elementu leżącego w w
-tym wierszu i k
-tej kolumnie
macierzy m
, piszemy m(w,k)
:
> m(1,2) ans = 2
> 1:4definiuje zakres odpowiadający ciągowi
[1, 2, 3, 4]
. Analogicznie
> 1 : 0.5 : 4.1odpowiada wektorowi
[1, 1.5, 2, 2.5, 3, 3.5, 4]
.
Zakresy nie tylko upraszczają zapis, ale przede wszystkim umożliwiają optymalizację
działania programu. Np. jeżeli zdefiniujemy zmienną a
wyrażeniem
> a = 1:100000to Octave zarezerwuje dla tej zmiennej zaledwie 24 bajty (3 liczby zmiennopozycyjne). Równoważny tej zmiennej wektor musiałby mieć 100 000 elementów i zajmowałby w pamięci operacyjnej aż 800 000 bajtów.
> a = "ala ma kota" a = ala ma kota
Transpozycja macierzy to zamiana jej kolumn na wiersze i wierszy na kolumny.
W Octave transpozycję macierzy wykonuje się za pomocą specjalnego operatora '
(apostrof).
Oto prosty przykład:
> m = [1, 2, 3; 4, 5, 6] m = 1 2 3 4 5 6 > b = m' b = 1 4 2 5 3 6
W powyższym przykładzie b
jest macierzą transponowaną do m
,
tj. b
czytana kolumnami wygląda tak samo, jak m
czytana wierszami.
Jednym z najważniejszym zastosowaniem transpozycji jest zamiana wektorów wierszowych na kolumnowe, wektorów kolumnowych na wierszowe i definiowanie „zakresów kolumnowych”. Tę ostatnią cechę ilustruje następujący przykład :
> v = [1:4]' v = 1 2 3 4
Uwaga: Jeżeli macierz m
ma elementy zespolone, to wyrażenie
m'
oznacza
sprzężenie hermitowskie m
. Transpozycję macierzy zespolonej oznacza się operatorem
.'
(kropka apostrof), np.
m = v.'
Dla macierzy rzeczywistych oba zapisy (z kropką lub bez) są równoważne.
W przypadku bardziej zaawansowanych obliczeń niezwykle ważna jest umiejętność zapisywania i wczytywania danych z plików. Szczególnie istotne jest zapisywanie końcowych wyników żmudnych obliczeń i wyników obliczeń pośrednich, które być może zechcemy kontynuować w przyszłości.
Aby zapisać dowolną zmienną, np. wektor a = [1,2,3,4,100]
, posługujemy się
poleceniem save
:
> save "a.mat" a
Pierwszym argumentem tego polecenia jest zwykle nazwa pliku (tu: a.txt
).
Następnie podajemy wykaz zmiennych, które chcemy w tym pliku zapisać (tu: jedna zmienna a
).
Oto przykład instrukcji zapisującej 3 zmienne, a
, x
i m
:
> save "axm.txt" a x m
Jeżeli nie podamy żadnych zmiennych, Octave zapisze w pliku wszystkie zdefiniowane aktualnie zmienne.
> save "sesja.txt"
Aby odczytać tak zapisane zmienne, stosujemy polecenie load
:
> load "axm.txt"
Warto zwrócić uwagę na to, że funkcja load
nie tylko wczytuje wartości zmiennych,
ale też nadaje im zapisane w piku nazwy.
Po wczytaniu zmiennych z pliku warto wydać polecenie who -l variables
> who -l -variables
które wyświetla podstawowe informacje o wszystkich zdefiniowanych aktualnie zmiennych.
Obie funkcje, save
i load
, posiadają mnóstwo dodatkowych opcji i potrafią
obsługiwać dane w wielu formatach, w tym w formatach binarnych programu Matlab.
> a = 1 > b = 1.0 > c = 1e0
> a = [1 2 3]; > b = [1, 2, 3]; > c = [1; 2; 3];
v
o elementach 1, 2, 5, 10
i zapisz go w pliku v.mat
.
v.mat
. Sprawdź, że w programie z powrotem pojawiła się zmienna v
.
v
z poprzedniego punktu sprawdź, jak Octave interpretuje wyrażenia
> v + v > v + 1 > v * 2 > v'
x
zapisana w binarnym formacie
hdf5.
x
(who -l variables
).x
(funkcjami rows
, columns
).x
(funkcjami min
, max
, mean
).