Tämä sivu perustuu Arto Wiklan ohjelmointisivustoon Materiaalin copyright © Arto Wikla. Materiaalia saa vapaasti käyttää itseopiskeluun. Muu käyttö vaatii luvan.

Algoritmi ja algoritmin tila

(Muutettu viimeksi 23.8.2010, sivu perustettu 20.8.2010.)

Algoritmisen ohjelmoinnin peruskäsitteitä ovat muuttuja (variable) ja sijoitusoperaatio (assignment operation).

Muuttuja tarkoittaa matematiikassa jotakin melko syvällistä: esimerkiksi ilmauksessa a+b=b+a väitetään vaikkapa minkä tahansa lukuparin summan olevan riippumaton laskentajärjestyksestä. Tilastotieteessä muuttuja voi tarkoittaa "selittävää tekijää"; esimerkiksi myytyjen jäätelöiden määrä voisi olla muuttujana hukkumiskuolemien määrää selitettäessä.

Algoritmisessa ohjelmoinnissa muuttuja on paljon konkreettisempi asia: muuttuja on arvon säilytyspaikka, "laatikko, jonka kyljessä on nimi". Laatikon sisältöa voi tutkia ja sisältöä voi muuttaa. Uuden sisällön asettamista laatikkoon kutsutaan sijoittamiseksi, sijoitusoperaatioksi tai sijoituslauseeksi.

Sijoitus korvaa muuttujan vanhan sisällön uudella. Uusi arvo voi olla jonkin laskutoimituksen, ns. lausekkeen (expression) arvo. Tuo lauseke voi sisältää vakioita, muuttujien arvoja ja laskutoimituksia.

Sijoitusoperaation ilmauksena algoritmeja kirjoitettaessa käytetään usein merkkijonoa ":=". Myös ilmausta "<-" näkee joskus. Valitettavasti eräissä ohjelmointikielissä (mm. Javassa!) sijoitusoperaation merkkinä käytetään yhtäsuuruusmerkkiä "=". Näissä kielissä matematiikasta tuttuun yhtäsuuruuden vertailuun joudutaan siten käyttämään matematiikan kielestä poikkeavaa ilmausta, esimerkiksi kahta yhtäsuuruusmerkkiä peräkkäin "==".

Esimerkki:
(Ilmaus var eka tarkoittaa, että määritellään muuttuja ("variable") nimeltä eka.)

  var eka = 7;
  var toka = 9 * eka;
  var kolm = (eka + toka) * 100;
  eka = eka + 1;

Huom: Sijoitusoperaatio kannattaa heti alussa opetella lukemaan "saa arvokseen", ei "on", vaikka ohjelmointikielessä Javan tapaan käytettäisiin yhtäsuuruusmerkkiä sijoitusoperaation ilmauksena! Erityisen hyvin tuo viimeinen esimerkki osoittaa, miksi.

     eka = eka + 1;

Ilmaus "eka on eka plus yksi" on looginen epätotuus. Sitävastoin "eka saa arvokseen eka plus yksi" ilmaisee, mistä on kysymys: ekan vanhaan arvoon lisätään yksi ja saatu summa sijoitetaan muuttujan eka uudeksi arvoksi.

Algoritmia siis suoritetaan ajassa: "ensin tehdään sitä, sitten tätä". Algoritmin muuttujien arvot kullakin ajan hetkellä muodostavat algoritmin ns. tilan (state). Ja oikeastaan kaikki tietokoneohjelmat ovat lopulta vain algoritmeja, jotka etenevät tilasta toiseen. Jos ohjelmassa näyttäisi olevan jotakin "viisautta", kyse on siitä, että ohjelman laatija on osannut rakentaa algoritmilleen sellaisen tilojen ketjun, joka ohjelman käyttäjästä vaikuttaa viisaalta.

Edellisen esimerkin tilat:


tila:     |__?____|  |__?____|  |__?____| 
            eka        toka       kolm

     eka = 7

tila:     |__7____|  |__?____|  |__?____| 
            eka        toka       kolm

     toka = 9 * eka

tila:     |__7____|  |__63___|  |__?____| 
            eka        toka       kolm

     kolm = (eka + toka) * 100

tila:     |__7____|  |__63___|  |__7000_| 
            eka        toka       kolm

     eka = eka + 1

tila:     |__8____|  |__63___|  |__7000_| 
            eka        toka       kolm

Algoritmi liitetään ympäristöönsä ns. syöttö- ja tulostusoperaatioin. Syöttöoperaation eli lukemisen seurauksena jokin muuttuja saa arvon ohjelman käyttäjältä tai vaikkapa jostakin tiedostosta. Lukeminen siis muuttaa ohjelman tilaa. Tulostusoperaatio, kirjoittaminen puolestaan laskee jonkin lausekkeen arvon ja siirtää tuloksen jollekin tulostuslaitteelle. Tällöin ohjelman tila ei muutu.

Syöttötietojen ajatellaan olevan syöttöjonossa, josta ne yksi kerrallaan luetaan. Tulostietojen ajatellaan puolestaan olevan tulosjonossa, johon ne yksi kerrallaan kirjoitetaan. Nämä jonot voivat ihan konkreettisestikin olla "jonoja" jossakin tiedostossa, mutta esimerkiksi vuorovaikutteisen ohjelman syötteiden ja tulosteiden "jonot" ovat pikemminkin jonoja ajassa.

Esimerkki:

  println("Anna kaksi lukua");
  var eka  = readInt;
  var toka = readInt;
  var kolmas = eka + toka;
  println("Niiden summa on");
  println(kolmas);

Jos tämän ohjelman syöttöjonossa on luvut 3 ja 4, muuttujaan eka luetaan arvo 3, muuttujaan toka arvo 4. Sitten muuttujaan kolmas sijoitetaan summa eka+toka eli arvo 7. Lopuksi ohjelma kirjoittaa tulosjonoon arvon 7. Näin "jonot" ovat siis ohjelman käyttäjän näkökulmasta toimintoja näytön ja näppäimistön äärellä.

Peräkkäin kirjoitetut operaatiot siis suoritetaan peräkkäin - "vasemmalta oikealle, ylhäältä alaspäin". Alkeisoperaatioiden (sijoitus, lukeminen, kirjoittaminen) suorittamista ohjataan ns. rakenteisin operaatioin. Monet rakenteiset operaatiot perustuvat siihen, että väitetään jotakin algoritmin tilasta, ja jos väite on tosi, "tehdään jotakin", jos epätosi, "tehdään jotakin muuta". Esimerkkejä tällaisista ovat valinta ja toisto:

Esimerkki valinnasta:

  println("Anna luku. Tutkin, onko se positiivinen");
  var luku = readInt;
  if (luku>0)             // valinta
    println("Luku on positiivinen.");
  else
    println("Luku ei ole positiivinen.");

Esimerkki toistosta:

  println("Moneenko kertaan haluat saada onnittelut?");
  var määrä = readInt;
  var monesko = 0;
  while (monesko < määrä) {      // toisto
    println("Onnea!");
    monesko = monesko + 1;
  }

Mitä seuraava ohjelmointivirheen sisältävä ohjelma tekee kun sille syötetään positiivinen luku? Entä kun sille syötetään negatiivinen luku? Simuloi ja opi! Mitä opit? Esimerkki toistosta:

  println("Moneenko kertaan haluat saada onnittelut?");
  var määrä = readInt;
  var monesko = 0;
  while (monesko > määrä) {      // toisto
    println("Onnea!");
    monesko = monesko + 1;
  }

Huom: Rakenteiset operaatiot ovat "rakenteisia" siksi, että niiden rakenneosina on muita lauseita. Noita rakenneosia voidaan kutsua alialgoritmeiksi: "Toistolause toistaa alialgoritmia..."

Lady Ada Lovelace, lordi Byronin tytär, keksi valinnan ja toiston 1800-luvun lopulla. Hän laati ohjelmia Charles Babbagen suunnittelemaan mekaaniseen tietokoneeseen, jossa ohjelmat suoritettiin suoraan reikäkorttipakalta. Lady Ada keksi täydentää konekieltä operaatioilla, jotka jostakin ehdosta riippuen hyppäävät joidenkin korttien ohi tai jotka siirtävät jo ohitetun korttipakan osan uudelleen luettavaksi!

Ehdollisuus - algoritmin tilasta riippuva toiminnan ohjaus - on keskeistä algoritmeja laadittaessa. Ilman ehdollisuutta algoritmi toimisi samoin kaikilla syöttötiedoilla! Alialgoritmien nimeäminen ja nimettyjen alialgoritmien kutsuminen on myös tärkeä väline: Kerran ohjelmoitua alialgoritmia ei tarvitse kirjoittaa uudelleen ja uudelleen.