Muistaminen ja laskeminen
Learning objectives
- Tutustut syvemmin käsitteeseen muuttuja ja opit, että muuttujilla voi olla erityyppisiä arvoja.
- Opit asettamaan muuttujan arvon uudelleen.
- Tutustut käsitteisiin lauseke ja liukuluku, ja opit tekemään laskentaa muuttujilla.
- Osaat kirjoittaa ohjelmia, jotka kysyvät käyttäjältä lukuja, ja tekevät niillä laskentaa.
Tietokoneen supertaidot: muistaminen ja laskeminen
Opimme edellisessä osassa kirjoittamaan ohjelmia, jotka kysyvät käyttäjältä syötettä ja jotka tulostavat tekstiä. Tällaisen ohjelman rakenne on seuraava.
import 'dart:io';
main() {
print('Kirjoita jotain!');
var syote = stdin.readLineSync();
print('Kirjoitit $syote');
}
Funktio print
tulostaa sille suluissa annettavan hipsuissa olevan merkkijonon. Lause var syote = stdin.readLineSync();
pyytää käyttäjältä syötettä, ja asettaa käyttäjän syötteen muuttujaan nimeltä syote
. Muuttujan arvoa voidaan käyttää tulostuksessa liittämällä muuttujan nimen eteen dollarimerkki $
, esim. $syote
.
Tarkastellaan käsitettä muuttuja hieman syvemmin.
Muuttujat ja arvon asettaminen
Muuttujia käytetään tiedon tallentamiseen ohjelman suorituksen ajaksi. Muuttuja luodaan tietokoneen muistiin kun se esitellään, jossa se pysyy ohjelman suorituksen ajan kunnes muuttujaa ei enää tarvita. Kuhunkin muuttujaan liittyy arvo, jonka voi vaihtaa (eli uudelleenasettaa) ohjelman suorituksen aikana.
Muuttujan esittely tapahtuu avainsanalla var
, jota seuraa muuttujan nimi. Tämän jälkeen tulee yhtäsuuruusmerkki, jota seuraa arvo, joka muuttujaan asetetaan. Alla olevassa esimerkissä luodaan muuttuja nimeltä vuosi
, johon asetetaan arvoksi luku 2020. Tämän jälkeen vuosi tulostetaan osana tulostuslausetta.
main() {
var vuosi = 2020;
print('Muuttujan vuosi arvo on $vuosi.');
}
program output
Muuttujan vuosi arvo on 2020.
Alla olevassa esimerkissä luodaan muuttuja nimi
, johon asetetaan merkkijono 'Ada Lovelace'. Tämän jälkeen nimi tulostetaan osana tulostuslausetta.
main() {
var nimi = 'Ada Lovelace';
print('Muuttujan nimi arvo on $nimi.');
}
program output
Muuttujan nimi arvo on Ada Lovelace.
Ohjelmassa voi olla useita muuttujia. Alla olevassa esimerkissä luodaan muuttujat nimi
ja syntymavuosi
, jonka jälkeen ne tulostetaan osana tulostuslausetta.
Kokeile yllä olevaa ohjelmaa. Mikäli ohjelma toimii, tulostuu sen tulosteeksi Ada Lovelace on syntynyt vuonna 1815.
Merkkijonot ja luvut
Edellä olevassa esimerkissä nimi 'Ada Lovelace' on hipsuissa, mutta syntymävuosi 1815 ei. Tässä on kyse siitä, miten tieto esitetään tietokoneohjelmissa. Merkkijonot asetetaan hipsuihin, mutta lukuja ei. Tulemme myöhemmin huomaamaan, että merkkijonoihin ja lukuihin liittyy niiden tyypille ominaisia operaatioita: esimerkiksi luvuilla voi laskea, mutta merkkijonoilla ei.
Käyttämässämme ohjelmointikielessä on kahdentyyppisiä lukuja: kokonaislukuja ja liukulukuja eli desimaalilukuja. Nämä poikkeavat toisistaan siinä, minkälaisia arvoja ne esittävät. Alla oleva esimerkki esittelee merkkijonot, kokonaisluvut, ja liukuluvut.
Yllä olevan ohjelman tulostus on seuraava. Voit myös kokeilla ohjelmaa itse sekä muuttaa sitä, jolloin tulostus muuttuu.
program output
nimi: Ada Lovelace vuosi: 1815 pii: 3.14
Vaikka luvut esitetään normaalisti ilman hipsuja, ei mikään estä ohjelmoijaa asettamasta lukua merkkijonoon. Mikäli luvun esittää hipsuissa, on se ohjelman suorituksen näkökulmasta merkkijono. Tulostuslauseen yhteydessä tällä ei ole käytännössä merkitystä.
main() {
var nimi = 'Ada Lovelace';
var syntymavuosi = '1815';
print('$nimi on syntynyt vuonna $syntymavuosi.');
}
program output
Ada Lovelace on syntynyt vuonna 1815.
Sallitut ja ei sallitut muuttujien nimet
Muuttujien nimentää määrää muutama sääntö. Tällä kurssilla muuttujien nimien tulee alkaa kirjaimella ja muuttujien nimissä saa esiintyä kirjaimia ja numeroita. Muuttujien nimissä ei saa olla välilyöntejä, eikä muuttujien nimissä saa esiintyä erityismerkkejä kuten vaikkapa yhtäsuuruusmerkkiä. Mikäli muuttuja kuvaa jotain asiaa, joka selitettäisiin useammalla sanalla, sanat yhdistetään siten, että ensimmäistä sanaa seuraavien sanojen ensimmäinen merkki kirjoitetaan isolla. Esimerkiksi muuttuja sananEnsimmainenMerkki
olisi sopiva nimi muuttujalle, joka kuvaa sanan ensimmäistä merkkiä.
Muuttujan arvon uudelleenasettaminen
Olemassaolevaan muuttujaan voi asettaa uuden arvon. Uuden arvon asettaminen muuttujaan johtaa siihen, että muuttujassa aiemmin ollut arvo katoaa. Alla olevassa esimerkissä tulostetaan kahden henkilön tiedot muuttujia nimi
ja syntymavuosi
käyttäen.
Yllä olevan ohjelman tulostus on seuraava.
program output
Ada Lovelace on syntynyt vuonna 1815. Alan Turing on syntynyt vuonna 1912.
Kukin muuttuja esitellään ohjelmassa vain kerran, eli silloin kun muuttuja tuodaan ohjelman käyttöön. Muuttujan esittely tapahtuu avainsanalla var
. Kun olemassaolevaan muuttujaan asetetaan uusi arvo, ei uuden arvon asetuksen yhteydessä muuttujan nimeä edellä avainsana var
.
Question not found or loading of the question is still in progress.
Muuttujan tyyppi ei muutu
Kun muuttujaan asetetaan uusi arvo, tulee sen olla saman tyyppinen kuin vanha arvo. Tämä tarkoittaa sitä, että mikäli muuttujaan on sen esittelyn yhteydessä asetettu merkkijono, ei muuttujan uudeksi arvoksi voi asettaa kokonaislukua. Vastaavasti, mikäli muuttujaan on sen esittelyn yhteydessä asetetettu kokonaisluku, ei muuttujan uudeksi arvoksi voi asettaa merkkijonoa.
Tämä johtuu siitä, että kun muuttuja esitellään, muuttujaan liitetään myös tieto sen tyypistä eli siitä onko muuttujan arvo esimerkiksi merkkijono tai kokonaisluku. Muuttujan tyyppiä ei voi vaihtaa sen jälkeen kun se on ohjelmassa kertaalleen asetettu.
Seuraava ohjelma ei esimerkiksi toimi, sillä luvun sisältävään muuttujaan syntymavuosi
yritetään asettaa merkkijono.
Question not found or loading of the question is still in progress.
Laskentaa
Muuttujan tyyppi määrää mitä muuttujalla voi tehdä. Merkkijonoilla ei voi esimerkiksi laskea -- mitä laskenta merkkijonoilla oikeastaan edes tarkoittaisi? -- mutta luvuilla laskeminen on mahdollista. Tutustutaan seuraavaksi laskutoimituksia tekevien ohjelmien luomiseen.
Luvuilla voi tehdä kaikki matemaatiikasta tutut peruslaskutoimitukset eli yhteenlaskuja, vähennyslaskuja, kertolaskuja, ja jakolaskuja.
Yllä olevan ohjelman tulostus on seuraava. Kokeile myös muuttaa ohjelmaa niin näet miten tulostus muuttuu.
program output
Kolme plus kaksi on 5 Kolme miinus kaksi on 1 Kolme kertaa kaksi on 6 Kolme jaettuna kahdella on 1.5
Yllä olevan ohjelmaesimerkin lauseet sisältävät lausekkeita. Lauseke (expression) on ohjelmoinnissa muuttujien ja arvojen kokoelma, joka tarkentuu (evaluoituu) yksittäiseksi arvoksi. Esimerkiksi 3 - 2
on lauseke, jonka arvoksi evaluoituu yksittäinen arvo eli 1
. Vastaavasti 3 * 2
on lauseke, jonka arvoksi evaluoituu 6
.
Ohjelmien toteuttama laskenta noudattaa matematiikasta tuttua laskujärjestystä:
- ensin lasketaan suluissa olevat laskut
- sitten lasketaan kerto- ja jakolaskut vasemmalta oikealle
- ja lopuksi lasketaan yhteen- ja vähennyslaskut vasemmalta oikealle
Tarkastellaan tätä lausekkeen 3 + ((2 + 8) * 4) - 1
kautta.
main() {
var luku = 3 + ((2 + 8) * 4) - 1;
print('Laskun tulos on $luku');
}
program output
Laskun tulos on 42
Lausekkeen 3 + ((2 + 8) * 4) - 1
arvo muodostuu seuraavalla tavalla.
- Ensin lasketaan sisimmät sulut eli
(2 + 8)
, jonka arvo on10
. - Tämän jälkeen lauseke on muodossa
3 + (10 * 4) - 1
. - Tätä seuraa suluissa olevan kertolaskun
(10 * 4)
laskeminen, jonka tulos on40
. - Tämän jälkeen lauseke on muodossa
3 + 40 - 1
. - Lopulta yhteen- ja vähennyslaskut lasketaan vasemmalta oikealle ja lopputulokseksi muodostuu
42
.
Muuttujien käyttäminen laskennassa
Laskemisessa voi hyödyntää muuttujien arvoja. Mikäli lausekkeessa esiintyy sekä lukuja että muuttujia, laskenta aloitetaan vaihtamalla muuttujien paikalle niiden arvot. Tarkastellaan tätä alla olevan laskun avulla.
main() {
var ensimmainen = 2;
var toinen = 8;
var luku = ensimmainen * (5 + toinen);
print('Laskun tulos on $luku');
}
program output
Laskun tulos on 26
Lausekkeen ensimmainen * (5 + toinen)
arvo muodostuu seuraavalla tavalla. Ensin vaihdetaan muuttujien ensimmainen
ja toinen
paikalle niiden arvot eli 2
ja 8
. Tämän jälkeen lauseke on 2 * (5 + 8)
. Tämän jälkeen lasketaan suluissa oleva lasku eli (5 + 8)
, jonka arvo on 13
. Tämän jälkeen lauseke on muodossa 2 * 13
. Lopulta kertolasku lasketaan ja tulokseksi muodostuu 26
.
Question not found or loading of the question is still in progress.
Matematiikka ja ohjelmointi
Joskus kuulee sanottavan, että ohjelmoinnin osaaminen vaatii erityistä matemaattista lahjakkuutta. Tämä on kuitenkin huuhaata. Ohjelmoinnissa voi kehittyä huipputason osaajaksi ilman erityistä matemaattista taustaa -- tärkeintä on pitkäjänteinen harjoittelu, aivan kuten missä tahansa muussakin asiassa.
Matemaattinen osaaminen vaikuttaa luonnollisesti matemaattisia ongelmia käsittelevien ohjelmointiongelmien ymmärtämiseen. Tämä saattaa olla yksi syy edellä esitetylle väärinkäsitykselle -- ohjelmoinnin oppimateriaaleissa ja opetuksessa on, ainakin historiallisesti, käytetty matemaattisia ongelmia osana ohjelmointiharjoittelua sillä tietokone on tehokas laskin.
Laskentaa käyttäjän syöttämillä luvuilla
Käyttäjältä luettu syöte on aina merkkijono. Mikäli haluamme muuntaa merkkijonon luvuksi, tulee se tehdä komennon int.parse
avulla. Komentoa int.parse
käytetään yhdessä syötteen lukemisen kanssa seuraavalla tavalla.
Mikäli käyttäjä syöttää merkkijonon 3
, ohjelma tulostaa Luettiin luku 3
. Vastaavasti, mikäli käyttäjä syöttää merkkijonon 8
, ohjelma tulostaa Luettiin luku 8
. Kokeile ohjelmaa alla.
Huutomerkki!
Muuttaessamme merkkijonoa luvuksi lauseen stdin.readLineSync()
perään tulee huutomerkki !
. Tällä kerromme, että ohjelma voi luottaa siihen, että lause stdin.readLineSync()
palauttaa arvon. Tällöin myös kutsu int.parse
voi luottaa siihen, että sille annetaan merkkijono, joka voidaan muuntaa luvuksi.
Tämä käytäntö liittyy Dart-kielen null safety -ominaisuuteen. Tässä kohtaa ohjelmointiopintoja voit vain ajatella, että huutomerkki tulee asettaa paikalleen.
Käyttäjältä luettuja lukuja voidaan käyttää laskentaan siinä missä muitakin lukuja. Alla olevassa esimerkissä käyttäjältä luetaan kaksi lukua, jonka jälkeen ohjelma laskee lukujen summan ja tulostaa sen.
Kun käyttäjä syöttää luvut 7
ja 21
, on ohjelman tulostus seuraavanlainen. Vaikka alla olevassa esimerkissä luvut 7
ja 21
näytetään syötteen kuvaamisen takia, ei ohjelma todellisuudessa tulosta kyseisiä lukuja.
program output
7 21 7 + 21 = 28
Desimaalilukujen käsittely
Totesimme aiemmin, että käyttämässämme ohjelmointikielessä on kahdentyyppisiä lukuja: kokonaislukuja ja liukulukuja (eli desimaalilukuja). Termi liukuluku (floating-point number) juontuu lukujen esityksestä tietokoneen muistissa -- jokaisella luvulla on käytössään rajattu määrä tilaa: liukuluvuilla desimaaliluvun desimaalin paikkaa voidaan liu'uttaa luvulle käytössä olevassa rajatussa tilassa.
Konkreettisesti tämä lukujen käytössä oleva rajattu tila näkyy joidenkin laskuoperaatioiden tuloksessa. Tarkastellaan seuraavia jakolaskuja.
main() {
var pieni = 10 / 3;
var iso = 10000000000 / 3;
print('$pieni');
print('$iso');
}
program output
3.3333333333333335 3333333333.3333335
Yllä olevasta esimerkistä huomaamme, miten kummankin jakolaskun tuloksen esittämiseen käytetään sama rajattu määrä lukuja, ja kummassakin on pieni pyöristysvirhe lopussa. Tästä ei ole kuitenkaan harmia, ellemme esimerkiksi käsittelisi ohjelmassamme rahoja tai muita lukuja, joiden käsittelyssä virheitä ei sallittaisi.
Tarkastellaan vielä hieman liukukuja sekä niiden käyttöä. Liukuluvun desimaalierottimena käytetään pistettä. Muuttuja pii
, johon asetetaan piin likiarvo 3.14
, luodaan seuraavalla tavalla.
main() {
var pii = 3.14;
print(pii);
}
program output
3.14
Kun ohjelmassa tehdään lasku kahdella kokonaisluvulla, on tulos joko kokonaisluku tai liukuluku. Tuloksen tyyppi -- eli onko tulos kokonaisluku vai liukuluku -- riippuu siitä, onko tulos mahdollista esittää kokonaislukuna. Alla olevassa esimerkissä ensimmäisen jakolaskun tulos on kokonaisluku, mutta toisen jakolaskun tulos on liukuluku.
main() {
var kokonaisluku = 10 / 2;
print(kokonaisluku);
var liukuluku = 10 / 4;
print(liukuluku);
}
program output
5 2.5
Pieniä eroja ohjelmointikielissä
Yllä oleva havainto pätee myös mikäli jompi kumpi tai kumpikin laskussa käytetyistä luvuista on liukuluku.
main() {
var kokonaisluku = 10.0 / 2.0;
print(kokonaisluku);
}
program output
5
Täm ä ei kuitenkaan päde kaikissa ohjelmointikielissä. Joissain ohjelmointikielissä kuten Javassa laskun tulos on aina liukuluku mikäli jompikumpi laskussa käytetyistä luvuista on liukuluku. Käyttämässämme Dart-kielessäkin tulos riippuu siitä, käytetäänkö Dart-kieltä JavaScriptiksi käännettynä ja sitä kautta tulkattuna (kuten tässä materiaalissa) vai suoraan ohjelmaksi käännettynä.
Liukuluvun lukeminen käyttäjältä
Merkkijonon muuntaminen liukuluvuksi onnistuu komennolla double.parse
. Sitä käytetään täysin samalla tavalla kuin komentoa int.parse
.
import 'dart:io';
main() {
print('Kirjoita luku.')
var luku = double.parse(stdin.readLineSync()!);
print('Luettiin luku $luku');
}
program output
Kirjoita luku. 0.25 Luettiin luku 0.25
Alla olevassa esimerkissä käytetään sekä kokonaisluvun että liukuluvun lukemista. Esimerkissä kuvattu ohjelma kysyy käyttäjältä ensin palkkaa, jonka jälkeen ohjelma kysyy veroprosenttia. Tämän jälkeen ohjelma tulostaa palkasta maksettavan veron määrän sekä jäljelle jäävän osan.
Alla on muutama esimerkkitulostus ohjelman käytöstä.
program output
Mikä on palkkasi (kokonaislukuna)? 2100 Mikä on veroprosenttisi (desimaalilukuna)? 17.5 Maksat veroa: 367.5 Jäljelle jää: 1732.5
program output
Mikä on palkkasi (kokonaislukuna)? 3000 Mikä on veroprosenttisi (desimaalilukuna)? 25.5 Maksat veroa: 765 Jäljelle jää: 2235
Tekoälyllä luotuja ohjelmointitehtäviä
Kurssimateriaalin ensimmäisissä osissa on tarjolla tekoälyllä luotuja ohjelmointitehtäviä. Voit kokeilla tällaisia tehtäviä alla. Valitse mieleisesi teema (Theme), harjoiteltava käsite (Concept), ja vaikeus (Difficulty). Paina tämän jälkeen "Get Exercise"-nappia.
Kurssialusta lataa tämän jälkeen tehtävänannon ja tehtävän, ja tarjoaa ohjelmointiympäristön tehtävän tekemiseen. Kun saat tehtävän valmiiksi, pyydämme sinulta palautetta ohjelmointitehtävästä.
Voit tehdä tekoälyllä luotuja tehtäviä niin paljon kuin haluat. Tehtävät ja tehtävänannot ovat toistaiseksi tarjolla vain englanniksi.
Loading exercises...
Hi! Please help us improve the course!
Please consider the following statements and questions regarding this part of the course. We use your answers for improving the course.
I can see how the assignments and materials fit in with what I am supposed to learn.
I find most of what I learned so far interesting.
I am certain that I can learn the taught skills and knowledge.
I find that I would benefit from having explicit deadlines.
I feel overwhelmed by the amount of work.
I try out the examples outlined in the materials.
I feel that the assignments are too difficult.
I feel that I've been systematic and organized in my studying.
How many hours (estimated with a precision of half an hour) did you spend reading the material and completing the assignments for this part? (use a dot as the decimal separator, e.g 8.5)
How would you improve the material or assignments?