Matemaattiset operaattorit

 

Laskutoimitukset

Laskutoimitusten suorittaminen C++:lla on helppoa kuin heinänteko. Pyydän anteeksi teiltä kaikilta maa- ja metsätalousihmisiltä, jotka ihan oikeasti olette joskus tehneet heinätöitä ja tiedätte, ettei se heinänteko oikeasti mitenkään hirveän helppoa ole. Me massat asumme kaupungissa.

Kun halutaan laskea jotakin yhteen, kirjoitetaan yksinkertaisesti muuttuja1 + muuttuja2. Voidaan sanoa, että tämä laskutoimitus palauttaa arvon. Arvo on muuttujien summa. Meidän tulee enää lopuksi sijoittaa tuo arvo jonnekin, eli saamme hahmoteltua tällaisen ohjelmanpätkän:

tulos = muuttuja1 + muuttuja2;

Väliin voi sujauttaa plussan tilalle minkä tahansa muunkin matemaattisen operaattorin. Operaattorien suoritusjärjestys on sama kuin matematiikassakin, ensin kerto- ja jakolaskut sekä jakojäännökset järjestyksessä vasemmalta oikealle, sitten plus- ja miinuslaskut vasemmalta oikealle. Sulkeilla voidaan järjestystä muuttaa - sulkeet käsitellään ennen muita laskuoperaatioita.

Operaattori Merkitys
+ yhteenlasku
- vähennyslasku
* kertolasku
/ jakolasku
% jakojäännös

 

Joitakin esimerkkejä vielä selventämään muutenkin niin selvää asiaa.

keskiNopeus = matka / aika;
keskiArvo = (arvo1 + arvo2) / 2;
koulunKoko = luokkienLkm * oppilaidenLkm + luokkienLkm * opettajiaPerLuokka + muuHenkilokunta;
koulunKoko = luokkienLkm * (oppilaidenLkm + opettajiaPerLuokka) + muuHenkilokunta; // sama kuin edellinen, kätevämmin esitettynä

 

Etuliiteoperaattorit

muuttuja = muuttuja + 1;

Kasvatamme taas luonnettasi perinteisin armeijan keinoin. Kirjoitapa tuo sata kertaa. Hyvä, nyt kerron kuinka olisit voinut tehdä sen paljon helpommin. <virnistys>

muuttuja++;

Muuttujan perään kirjoitettu ++ -operaattori kasvattaa muuttujan arvoa yhdellä. Vastaavasti löytyy myös -- -operaattori, joka pienentää muuttujaa yhdellä. Kätevyyden lisäksi nämä operaattorit voivat olla myös nopeampia, kääntäjästä ja ympäristöstä riippuen.

Voidaan kirjoittaa myös --a tai ++a. Näillä on kuitenkin yksi tärkeä ero: ++a käsitellään niin, että ensin a-muuttujaan lisätään yksi ja sitten sitä käytetään muussa lauseessa. a++ taas käsitellään toisin päin: ensin käytetään a:ta ja sitten kasvatetaan sitä. Jos halutaan vain muuttaa muuttujan arvoa, ei merkintätavoilla ole eroa, mutta jos käytetään muuttujaa samassa yhteydessä muuhunkin, kuten vaikka taulukon indeksinä, ero tulee näkyviin.

b=taulukko[++a] kasvattaa a:ta yhdellä ja sitten ottaa arvon taulukosta a:n kasvatetulla arvolla ja sijoittaa sen b:hen. b=taulukko[a++] taas ottaa taulukon alkion a:n alkuperäisen arvon kohdalta, sijoittaa sen b:hen ja lopuksi vasta kasvattaa a:ta.

Jos haluammekin kasvattaa muuttujaa kahdella, mutta emme jaksa kirjoittaa a=a+2, niin voimme käyttää kätevää +=operaattoria. a +=2. Ei liene enää yllätys, että -=vastaavasti vähentää. Näistä operaattoreista löytyy myös kerto- ja jakolaskut sekä jakojäännös.

Operaattori Merkitys
+= lisää muuttujan arvoa
-= vähentää muuttujan arvoa
*= kertoo muuttujan luvulla
/= jakaa muuttujan luvulla
%= sijoittaa muuttujaan jakojäännöksen

Esimerkiksi:

muuttuja += 2; // kasvattaa muuttujaa kahdella
muuttuja *= 2; // muuttuja kaksinkertaistetaan
muuttuja %= 3; // sijoittaa jakolaskun (muuttuja / 3) jakojäännöksen muuttujaan
muuttuja %= 2; // muuttuja on 0 jos parillinen, 1 jos pariton

 

Aivojumppaa: uhmaako a=a + 1; todellisuuden luonnetta?

Muuttujan a kasvattaminen lauseella a = a + 1; voi vaikuttaa järjettömältä. Kuinka a voi olla yhtäsuuri kuin a plus yksi? Ja kuinka a:han voidaan sijoittaa sitä yhtä suurempi arvo? Eikö siitä synny ikuinen silmukka, kun a:n pitää olla itseään suurempi?

Täyttä typerehtimistä tuollaiset pohdinnot eivät todellakaan ole. Pulma ratkeaa, kun muistaa, että a:n ei todeta olevan itseään suurempi, vaan esitetään toivomus että a olisi yhtä suurempi. Vertailuoperaattori == on erikseen: lauseke a == a + 1 on myös mahdollinen ja se palauttaa aina epätoden arvon - koska muuttujan a:n arvo ei tietenkään voi olla yhtä suurempi itseään. Tämä juttu siis vaikuttaa aika selvältä. Mutta kuinka a:n arvo voi olla itseään suurempi, siinäpä sitä onkin metafyysistä mussutettavaa kokonaiselle filosofien yhdyskunnalle.

a:n ongelmaa pitää lähestyä tietokoneiden ja C++-kielen sarjamuotoisen toiminnan kautta. Mitkään asiat eivät tapahdu yhtä aikaa. Kääntäjä käsittelee lauseen näin; ensin luetaan muuttujan a arvo muistista, lisätään siihen yksi ja sitten sijoitetaan se muistiin muuttujan a kohdalle. Ensin haetaan ja sijoitetaan, siis oikea puoli suoritetaan ensin. Käytännössä kääntäjä tekee näin:

int b = a + 1;
a = b;

Kääntäjä sijoittaa ensin oikean puolen arvon väliaikaiseen muuttujaan (jonka C++-kääntäjä sijoittaa prosessorin nopeisiin rekistereihin) ja vasta sen jälkeen sijoittaa sen muuttujaan a. C++-kielisesti siis a = a + 1 ei ole yksi lauseke, vaan kaksi lauseketta: (a = (a + 1)), joista sisimmäinen suoritetaan ensin.

Tästä seuraa myös, että kun käsketään näin:

a = 5;
b = a + 1;
a = 6;

..niin lopuksi muuttujan b arvo ei ole seitsemän, vaan kuusi. Ilmaus b = a + 1 ei ole mikään sääntö, joka sen esittämisen jälkeen pätee aina. Se on vain sijoitus käskyjen perättäisessä virrassa, eikä sijoituksen pohjalta voida b:n arvosta olla varmoja kuin seuraavassa lauseessa.

C++-kielinen ohjelma siis toimii askel kerrallaan, se ratkaisee tämän pulman. Käytännössä nykyaikaisilla prosessoreilla voidaan suorittaa useita käskyjä kerrallaan, mutta siinäkin tapauksessa kaikki on koodattu perättäiseksi, mutta suoritetaan enemmän tai vähemmän onnistuneesti yhtäaikaisesti. C++-ohjelma voidaan yhä ajatella sarjamuotoisena, prosessori vaan ripsauttelee rinnakkain useita käskyjä kun se ei sotke ohjelman toimintaa. Tätä teknistä hankaluttaa ei C++-ohjelmoijan tarvitse ajatella, ellei rupea kirjoittamaan konekieltä C++-ohjelmiensa sekaan. Toki C++:lla voidaan tehdä ohjelmia joita ihan oikeasti ja aidosti suoritetaan useasta kohdasta yhtä aikaa. Siihen tarvitaan ympäristö, joka tukee säikeitä (thread of execution) ja se on oikein tehtynä hyvin hankalaa. Moni ammattiohjelmoijakaan ei tarvitse säikeitä ja moniprosessointia, joten sinäkin voit sellaiset hankaluudet vielä unohtaa.

Takaisin