Jorin jutut / Matlab

Ohjausrakenteet Matlabissa

Kuten kaikissa ohjelmointikielissä, myös Matlabissa ohjelman toiminta perustuu kolmeen ohjausrakenteeseen:

Peräkkäisyyttä ei tarvitse erikseen merkitä, funktiossa peräkkäin kirjoitetut lauseet suoritetaan järjestyksessä.

Ehdollisuus

if, else ja elseif

Ehdollisuus tehdään if-rakenteella, monimutkaisemmissa tapauksissa käytetään if-elseif-elseif-...-else-rakennetta.

Yksinkertainen esimerkki:

function kuinka_iso_kenka(kengan_numero)
if kengan_numero > 45
   disp('Olet isokenkäinen');
end

Hiukan monimutkaisempi tapaus on if-else-rakenne:

function kuinka_iso_kenka2(kengan_numero)
if kengan_numero > 45
   disp('Olet isokenkäinen');
else
   disp('Pienikenkäinen');
end

Esimerkki elseif-rakenteesta:

function arvostele_jalka(kengan_numero)
if kengan_numero < 37
   disp('Pikkuiset jalat');
elseif kengan_numero < 40
   disp('Aika pieni');
elseif kengan_numero < 45
   disp('Tavanomaiset koivet');
else
   disp('Isot tassut!');
end

switch-case -rakenne

Toisinaan pitää tehdä monen vaihtoehdon perusteella jotain. Tämä onnistuu riittävällä määrällä elseif-lauseita, mutta helpommalla pääsee switch-lauseen avulla:

function tulos=arvostele(arvosana)
switch arvosana
case 1
   tulos='Voi ei';
case 2
   tulos='OK';
case 3
   tulos='Hienoa';
   disp('Kolmosen sai...');
otherwise
   tulos='xxx';
   disp('VIRHE!!!');
end

Funktiossa rivinvaihdon voi korvata pilkulla ja puolipisteellä erotettuja lauseita saa olla peräkkäinkin. Tällainen vastaa edellistä esimerkkiä:

function tulos=arvostele(arvosana)
switch arvosana, case 1, tulos='Voi ei';
case 2, tulos='OK'; case 3, tulos='Hienoa';
disp('Kolmosen sai...'); otherwise, tulos='xxx'; disp('VIRHE!!!');
end

Käytännössä näin sotkuista ohjelmaa ei saa tehdä. Itse hylkään sellaiset harjoitustyöt, jotka muistuttavat ylläolevaa.

Toistoa, toistoa, toistoa, toistoa

Toistorakenteita Matlabissa on kaksi, while- ja for-lauseet. Viimeksimainittua käytetään yleensä, kun toistettavien kierrosten lukumäärä tiedetään etukäteen. Ensinmainittu sopii tilanteeseen, jossa tehdään jotain niin kauan, kunnes saavutetaan haluttu tila.

for-lause

Aloitetaan yksinkertaisella komentoriviesimerkillä:

» summa=0; luvut=[4 1 5];
» for i=luvut, summa=summa+i, end
summa =
     4
summa =
     5
summa =
    10

for-lauseen syntaksi on siis: for muuttuja=vektori, runko, end

Edellisessä esimerkissä muuttuja oli i, vektori oli luvut ja runko oli summa=summa+i. for-lause suoritettiin niin, että muuttuja i sai järjestyksessä jokaisen vektorin luvut arvon ja runko summa=summa+i suoritettiin jokaisella arvolla.

Käytännössä useimmiten tehdään jokin silmukka arvoilla 1..n. Tämä on helppoa, tehdään ensin vektori, jonka alkioina on haluttu lukuväli ja käytetään tätä for-silmukassa. Välttämättä ei väliaikaista muuttujaa tarvitse tehdä. Nämä molemmat laskevat lukujen 1..10 neliöjuurten summan:

» m=1:10; summa=0; for i=m, summa=summa+sqrt(i); end; disp(summa)
   22.4683
» summa=0; for i=1:10, summa=summa+sqrt(i); end; disp(summa)
   22.4683

... ja esimerkiksi funktio, joka laskee keskiarvon, on tällainen:

function ka=keskiarvo(luvut)
summa=0;
n=length(luvut);
for i=1:n
   summa=summa+luvut(i);
end
ka=summa/n;

while-lause

Jos halutaan suorittaa jotain niin kauan, kuin jokin ehto on voimassa, käytetään while-lausetta. Ehto on usein jokin suuruusrelaatio, esimerkiksi tässä k>0

» k=3
k =
     3
» while k>0, k=k-1, end
k =
     2
k =
     1
k =
     0

Mitä while-lause tekisi, jos muuttujan k arvo olisi 3.5? Kokeile!

Käytännössä while-sana on aina osa ohjelmaa. Tehdäänpä harjoituksen vuoksi jakolasku vähennyslaskujen avulla:

function osamaara=jaa(jaettava, jakaja)
osamaara=0;
while (jaettava > 0)
   osamaara = osamaara+1;
   jaettava = jaettava-jakaja;
end

Ohjelmat tehdään yhdistämällä näitä perusrakenteita. if-lauseen sisällä voi olla for-lause, jonka sisällä voi olla if-lause, jonka sisällä voi olla while-lause, jonka sisällä...

Esimerkkinä lauseiden yhdistämisestä esitellään luvunarvauspeli:

% Luvunarvauspeli  -  2000-03-15  -  Jori Mäntysalo
%
% Funktio saa parametrinaan oikean luvun, jonka käyttäjä
% yrittää arvata. Paluuarvona on arvausten lukumäärä.

function yritysten_maara=luvunarvaus(oikea_luku)
disp('Tervetuloa luvunarvauspeliin');
arvaus = oikea_luku-1;  % Estää 1. while -lauseen toteutumisen
yritysten_maara = 0;
while (arvaus ~= oikea_luku)
   yritysten_maara = yritysten_maara+1;
   arvaus=input('Arvaa luku: ');
   if arvaus < oikea_luku
      disp('Liian pieni');
   elseif arvaus > oikea_luku
      disp('Liian suuri');
   end
end

Mitä vielä?

Matlabissa on myös try-catch-rakenne, jolla voidaan käsitellä virhetilanteita. Toisinaan tarvitaan myös break-sanaa. Näistä saat lisätietoa sanomalla help try ja help break.

Miten oikeasti toimitaan

Ylläolevat kappaleet kertovat, miten Matlabia voi käyttää "normaalin" ohjelmointikielen tapaan. Yleensä tähän ei ole tarvetta, Matlabilla voidaan tehdä kätevämmin ohjelmia käsittelemällä kokonaisia vektoreita tai matriiseja kerrallaan.

Useimmat funktiot toimivat suoraan vektorin kaikille alkioille tai laskevat jotain koko vektorista. Niinpä ylempänä laskettu lukujen 1..10 neliöjuurien summa saadaan helpommin (ja nopeammin) sanomalla

» m=1:10; tilap=sqrt(m); summa=sum(tilap)
summa =
   22.4683

Tai myös ilman välituloksia

» summa=sum(sqrt(1:10))
summa =
   22.4683

Myös if-lause saadaan usein korvattua vektorimuotoisella laskulla. Katsotaan ensin, miten muodostetaan looginen vektori suurempi-kuin -operaattorin avulla:

» v1=[7 3 8 2]; v2=[6 4 8 1];
» i=v1 < 7
i =
     0     1     0     1
» whos
  Name      Size         Bytes  Class

  i         1x4             32  double array (logical)
  v1        1x4             32  double array
  v2        1x4             32  double array

Grand total is 12 elements using 96 bytes

Tämän jälkeen voidaan käyttää loogista vektoria i indeksointiin:

» v1(i)
ans =
     3     2

Ja voidaan myös sijoittaa vektoriin halutuille pakoille arvoja:

» v1(i)=0
v1 =
     7     0     8     0

Tämän jälkeen onkin helppo tehdä tutustumiskierroksen lopussa ollut funktio testi2 ilman if-lausetta.

% Paloittain määritelty funktio
% testi3(x) = -x^2, kun x<0
% testi3(x) = x^2, kun x>=0
function y=testi3(x)
negatiiviset = x<0;
positiiviset = x>=0;
y(negatiiviset) = x(negatiiviset).^2;
y(positiiviset) = -x(positiiviset).^2;

Nyt funktio toimii paitsi yksittäiselle luvulle, myös vektorille. Voit siis vaikkapa piirtää kuvaajaan funktiosta normaaliin tapaan.