Laskentaa luvuilla
Laskuoperaatiot ovat tuttuja ja suoraviivaisia: yhteenlasku +
, erotus -
, kertolasku *
ja jakolasku /
. Laskentajärjestys on myös tuttu: laskenta tehdään vasemmalta oikealle sulut huomioon ottaen. Kuitenkin *
ja /
lasketaan ennen +
ja -
operaatioita, samoin kuin perus- tai kansakoulumatematiikassa on tullut tutuksi.
int eka = 2;
System.out.println(eka); // tulostaa 2
int toka = 4;
System.out.println(toka); // tulostaa 4
int summa = eka + toka; // muuttujaan summa asetetaan muuttujien eka ja toka arvojen summa
System.out.println(summa); // tulostaa 6
Laskujärjestys ja sulut
Laskujärjestykseen voi vaikuttaa sulkujen avulla. Sulkujen sisällä olevat laskuoperaatiot suoritetaan ennen niiden ulkopuolella olevia laskuoperaatioita.
int laskuSuluilla = (1 + 1) + 3 * (2 + 5);
System.out.println(laskuSuluilla); // tulostaa 23
int laskuSuluitta = 1 + 1 + 3 * 2 + 5;
System.out.println(laskuSuluitta); // tulostaa 13
Yllä olevan esimerkin voi jakaa myös osiin.
int laskuSuluilla = (1 + 1);
System.out.println(laskuSuluilla); // tulostaa 2
laskuSuluilla = laskuSuluilla + 3 * (2 + 5);
System.out.println(laskuSuluilla); // tulostaa 23
int laskuSuluitta = 1 + 1;
laskuSuluitta = laskuSuluitta + 3 * 2;
laskuSuluitta = laskuSuluitta + 5;
System.out.println(laskuSuluitta); // tulostaa 13
Lausekkeen evaluointi tapahtuu ohjelmakoodissa siinä kohtaa, missä lauseke on. Evaluointi onnistuu siis esimerkiksi myös tulostuslauseen yhteydessä, jos lauseketta käytetään tulostuslauseen parametrin arvon laskemisessa.
int eka = 2;
int toka = 4;
System.out.println(eka + toka); // tulostaa 6
System.out.println(2 + toka - eka - toka); // tulostaa 0
Lauseke ei muuta muuttujassa olevaa arvoa, ellei lausekkeen lopputulosta aseteta muuttujan arvoksi tai anneta parametrina esimerkiksi tulostukselle.
int eka = 2;
int toka = 4;
// alla oleva lauseke ei edes toimi, sillä lauseketta
// ei aseteta minkään muuttujan arvoksi tai anneta parametrina
// tulostuslauseelle
eka + toka;
Laskentaa ja tulostamista
Muuttujan arvon voi tulostaa komennolla System.out.println
. Tulostettavaan hipsuilla merkittyyn merkkijonoon, esim. "Pituus ", voidaan lisätä muuta tulostettavaa operaation +
avulla.
int pituus = 42;
System.out.println("Pituus " + pituus);
Pituus 42
System.out.println("tuossa on kokonaisluku --> " + 2);
System.out.println(2 + " <-- tuossa on kokonaisluku");
tuossa on kokonaisluku —> 2 2 <— tuossa on kokonaisluku
Jos toinen operaation +
kohteista on merkkijono, muutetaan myös toinen operaation kohteista merkkijonoksi ohjelman suorituksen yhteydessä. Alla olevassa esimerkissä kokonaisluku 2
on muutettu merkkijonoksi "2", ja siihen on yhdistetty merkkijono.
Aiemmin esitellyt laskusäännöt pätevät täälläkin:
System.out.println("Neljä: " + (2 + 2));
System.out.println("Mutta! kaksikymmentäkaksi: " + 2 + 2);
Neljä: 4 Mutta! kaksikymmentäkaksi: 22
Edellistä tietoa soveltamalla voimme luoda lausekkeen, joka sisältää tekstiä ja muuttujan, ja joka evaluoidaan tulostuksen yhteydessä:
int x = 10;
System.out.println("muuttujan x arvo on: " + x);
int y = 5;
int z = 6;
System.out.println("y on " + y + " ja z on " + z);
Tulostus:
muuttujan x arvo on: 10 y on 5 ja z on 6
Kun olet saanut edellisen tehtävän toteutettua, kokeile mikä on suurin mahdollinen kertolasku minkä saat laskettua. Huomaamasi ilmiön taustalla on se, että kokonaislukumuuttujan arvo voi olla korkeintaan 231-1 eli 2147483647. Tämä johtuu siitä, että kokonaislukumuuttujat esitetään tietokoneen muistissa 32 bitin avulla. Tähän tutustutaan tarkemmin muunmuassa kurssilla Tietokoneen toiminta.
Jakolasku
Kokonaislukujen jakolasku on hieman hankalampi operaatio. Jakolausekkeessa käytettyjen muuttujien tyyppi määrää evaluaation tuloksena saatavan arvon tyypin. Jos kaikki jakolausekkeessa olevat muuttujat ovat kokonaislukuja, on tulos myös kokonaisluku.
int tulos = 3 / 2;
System.out.println(tulos);
1
Edellinen esimerkki tulostaa luvun 1, sillä 3 ja 2 ovat kokonaislukuja ja kahden kokonaisluvun jakolaskun tulos on kokonaisluku.
int eka = 3;
int toka = 2;
double tulos = eka / toka;
System.out.println(tulos);
1
Nytkin tulostus on 1, sillä eka ja toka ovat (yhä) kokonaislukuja.
Jos jakolaskun jakaja tai jaettava (tai molemmat!) ovat liukulukuja, tulee tulokseksi myös liukuluku.
double kunJaettavaOnLiukuluku = 3.0 / 2;
System.out.println(kunJaettavaOnLiukuluku); // tulostaa 1.5
double kunJakajaOnLiukuluku = 3 / 2.0;
System.out.println(kunJakajaOnLiukuluku); // tulostaa 1.5
1.5 1.5
Kokonaisluku voidaan tarvittaessa muuttaa liukuluvuksi lisäämällä sen eteen tyyppimuunnosoperaatio (double)
:
int eka = 3;
int toka = 2;
double tulos1 = (double) eka / toka;
System.out.println(tulos1); // tulostaa 1.5
double tulos2 = eka / (double) toka;
System.out.println(tulos2); // tulostaa 1.5
double tulos3 = (double) (eka / toka);
System.out.println(tulos3); // tulostaa 1.0
1.5 1.5 1.0
Jälkimmäisessä esimerkissä tulos pyöristyy väärin sillä laskuoperaatio kokonaisluvuilla suoritetaan ennen tyyppimuunnosta.
Jos jakolausekkeen tulos asetetaan kokonaislukutyyppiseen muuttujaan, on tulos automaattisesti kokonaisluku.
int kokonaisluku = 3.0 / 2;
System.out.println(kokonaisluku);
1
Seuraava esimerkki tulostaa "1.5", sillä jaettavasta tehdään liukuluku kertomalla se liukuluvulla (1.0 * 3 = 3.0) ennen jakolaskua.
int jaettava = 3;
int jakaja = 2;
double tulos = 1.0 * jaettava / jakaja;
System.out.println(tulos);
1.5
Muuttujan arvoon liittyviä väärinkäsityksiä
Kun tietokone suorittaa ohjelmakoodia, suorittaa se sitä käsky kerrallaan, edeten aina täsmälleen siten, kuin ohjelmakoodissa sanotaan. Kun muuttujaan asetetaan arvo, tapahtuu aina sama asia, eli yhtäsuuruusmerkin oikealla puolella oleva arvo kopioidaan yhtäsuuruusmerkin vasemmalla puolella olevan muuttujan arvoksi, eli muuttujan nimeämään paikkaan.
On tärkeää, että ohjelmoija ymmärtää, että arvon asettaminen muuttujaan tekee aina saman asian.
Kolme yleistä väärinkäsitystä, jotka liittyvät muuttujan arvon asettamiseen ovat seuraavat:
-
Muuttujan asettamisen näkeminen siirtona kopioimisen sijaan: ohjelmakoodin
eka = toka
suorituksen jälkeen ajatellaan, että muuttujantoka
arvo on siirtynyt muuttujaneka
arvoksi, jonka jälkeen muuttujallatoka
ei ole enää arvoa, tai sen arvo on esimerkiksi nolla. Tämä ei pidä paikkansa, sillä ohjelmakoodineka = toka
suorituksessa muuttujantoka
nimeämässä paikassa oleva arvo kopioidaan muuttujaneka
nimeämään paikkaan. Muuttujantoka
arvo ei siis muutu. -
Muuttujan asettamisen näkeminen riippuvuutena kopioimisen sijaan: ohjelmakoodin
eka = toka
suorituksen jälkeen ajatellaan, että mikä tahansa muutos muuttujaantoka
vaikuttaa automaattisesti myös muuttujaaneka
. Tämä ei pidä paikkansa, sillä asetus — kopiointi — on yksittäinen tapahtuma. Se tapahtuu vain silloin, kun ohjelmakoodieka = toka
suoritetaan. -
Kolmas väärinkäsitys liittyy kopioimisen suuntaan: ohjelmakoodin
eka = toka
suorituksessa ajatellaan, että muuttujantoka
arvoksi kopioidaan muuttujaneka
arvo. Tämä näkyy myös tilanteina, missä ohjelmoija voi vahingossa kirjoittaa esimerkiksi42 = arvo
— onneksi ohjelmointiympäristöt tukevat myös tässä.
Ehkäpä paras tapa tietokoneen ohjelmakoodin suorittamisen ymmärtämiseen on paperin ja kynän käyttäminen. Kun luet ohjelmakoodia, kirjoita paperille uusien muuttujien nimet, sekä kirjoita ylös rivi riviltä, miten ohjelmakoodissa olevien muuttujien arvot muuttuvat. Havainnollistetaan suoritusta seuraavalla ohjelmakoodilla:
rivi 1: int eka = (1 + 1);
rivi 2: int toka = eka + 3 * (2 + 5);
rivi 3:
rivi 4: eka = 5;
rivi 5:
rivi 6: int kolmas = eka + toka;
rivi 7: System.out.println(eka);
rivi 8: System.out.println(toka);
rivi 9: System.out.println(kolmas);
Alla on kirjoitettu yllä olevan ohjelmakoodin suoritus auki.
rivi 1: luodaan muuttuja eka rivi 1: kopioidaan muuttujan eka arvoksi laskun 1 + 1 tulos rivi 1: muuttujan eka arvo on 2 rivi 2: luodaan muuttuja toka rivi 2: lasketaan 2 + 5, 2 + 5 -> 7 rivi 2: lasketaan 3 * 7, 3 * 7 -> 21 rivi 2: lasketaan eka + 21 rivi 2: kopioidaan muuttujan eka arvo laskuun, muuttujan eka arvo on 2 rivi 2: lasketaan 2 + 21, 2 + 21 -> 23 rivi 2: kopioidaan muuttujan toka arvoksi 23 rivi 2: muuttujan toka arvo on 23 rivi 3: (tyhjä, ei tehdä mitään) rivi 4: kopioidaan muuttujan eka arvoksi 5 rivi 4: muuttujan eka arvo on 5 rivi 5: (tyhjä, ei tehdä mitään) rivi 6: luodaan muuttuja kolmas rivi 6: lasketaan eka + toka rivi 6: kopioidaan muuttujan eka arvo laskuun, muuttujan eka arvo on 5 rivi 6: lasketaan 5 + toka rivi 6: kopioidaan muuttujan toka arvo laskuun, muuttujan toka arvo on 23 rivi 6: lasketaan 5 + 23 -> 28 rivi 6: kopioidaan muuttujan kolmas arvoksi 28 rivi 6: muuttujan kolmas arvo on 28 rivi 7: tulostetaan muuttuja eka rivi 7: kopioidaan muuttujan eka arvo tulostettavaksi, muuttujan eka arvo on 5 rivi 7: tulostetaan arvo 5 rivi 8: tulostetaan muuttuja toka rivi 8: kopioidaan muuttujan toka arvo tulostettavaksi, muuttujan toka arvo on 23 rivi 8: tulostetaan arvo 23 rivi 9: tulostetaan muuttuja kolmas rivi 9: kopioidaan muuttujan kolmas arvo tulostettavaksi, muuttujan kolmas arvo on 28 rivi 9: tulostetaan arvo 28
Alla edellinen ohjelma askeleittain visualisoituna. Käytössä oleva askeleittainen visualisointi käsittelee ohjelmakoodia riveittäin — pohdi askeleiden kohdalla miten ohjelma päätyy sen tulostamaan lopputulokseen.
Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!