Diskreetit rakenteet P 5 op

Samankaltaiset tiedostot
811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

Diskreetit rakenteet. Juha Kortelainen

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

Kappale 20: Kantaluvut

5. Laskutoimitukset eri lukujärjestelmissä

Paavo Räisänen. Ohjelmoijan binaarialgebra ja heksaluvut.

Ohjelmoinnin perusteet Y Python

1 Peruslaskuvalmiudet

Ohjelmoijan binaarialgebra ja heksaluvut

ANSI/IEEE Std

Lukujärjestelmät. Digitaalitekniikan matematiikka Luku 9 Sivu 3 (26) Lukujärjestelmät ja lukujen esittäminen Fe

LUKUTEORIA johdantoa

811120P Diskreetit rakenteet

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Matematiikan tukikurssi

Liukulukulaskenta. Pekka Hotokka

C = P Q S = P Q + P Q = P Q. Laskutoimitukset binaariluvuilla P -- Q = P + (-Q) (-Q) P Q C in. C out

OHJ-1010 Tietotekniikan perusteet 4 op Syksy 2012

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 12 (opetusmoniste, kappaleet )

Ohjelmoinnin perusteet Y Python

11. Javan toistorakenteet 11.1

Ohjelmoinnin perusteet Y Python

Algoritmit 1. Luento 1 Ti Timo Männikkö

Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa

Palautteita. Tutoriaalit olivat vaikeat! Totta, tentti on onneksi helpompi

1. Logiikan ja joukko-opin alkeet

Python-ohjelmointi Harjoitus 2

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8

(1) refleksiivinen, (2) symmetrinen ja (3) transitiivinen.

Numeeriset menetelmät

Matematiikassa ja muuallakin joudutaan usein tekemisiin sellaisten relaatioiden kanssa, joiden lakina on tietyn ominaisuuden samuus.

ITKP102 Ohjelmointi 1 (6 op)

SISÄLLYS - DIGITAALITEKNIIKKA

Sekalaiset tehtävät, 11. syyskuuta 2005, sivu 1 / 13. Tehtäviä

Matematiikan johdantokurssi, syksy 2016 Harjoitus 11, ratkaisuista

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

811120P Diskreetit rakenteet

Miten perustella, että joukossa A = {a, b, c} on yhtä monta alkiota kuin joukossa B = {d, e, f }?

Desimaaliluvut, mitä ne oikeastaan ovat?

1. Kirjoita algoritmi, joka saa syötteenä pallon säteen ja tulostaa pallon tilavuuden.

Vastaus 1. Lasketaan joukkojen alkiot, ja todetaan, että niitä on 3 molemmissa.

Ohjelmoinnin perusteet Y Python

12. Javan toistorakenteet 12.1

Testaa taitosi 1: Lauseen totuusarvo

Injektio. Funktiota sanotaan injektioksi, mikäli lähtöjoukon eri alkiot kuvautuvat maalijoukon eri alkioille. Esim.

Vaihtoehtoinen tapa määritellä funktioita f : N R on

Rekursio. Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on

n! k!(n k)! n = Binomikerroin voidaan laskea pelkästään yhteenlaskun avulla käyttäen allaolevia ns. palautuskaavoja.

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Merkitse kertolasku potenssin avulla ja laske sen arvo.

MS-A0402 Diskreetin matematiikan perusteet

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Ongelma(t): Miten tietokoneen komponentteja voi ohjata siten, että ne tekevät yhdessä jotakin järkevää? Voiko tietokonetta ohjata (ohjelmoida) siten,

Salausmenetelmät. Veikko Keränen, Jouko Teeriaho (RAMK, 2006)

1 Lukujen jaollisuudesta

2017 = = = = = = 26 1

Lukuteorian kertausta

811120P Diskreetit rakenteet

MS-A0402 Diskreetin matematiikan perusteet

Ohjelmoinnin peruskurssi Y1

Approbatur 3, demo 1, ratkaisut A sanoo: Vähintään yksi meistä on retku. Tehtävänä on päätellä, mitä tyyppiä A ja B ovat.

7. Laskutoimitukset eri lukujärjestelmissä 1 / 31

Lisää kvanttoreista ja päättelyä sekä predikaattilogiikan totuustaulukot 1. Negaation siirto kvanttorin ohi

Matematiikan tukikurssi, kurssikerta 3

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Algoritmit 2. Luento 8 To Timo Männikkö

1. Osoita, että joukon X osajoukoille A ja B on voimassa toinen ns. de Morganin laki (A B) = A B.

Java-kielen perusteet

Joukot. Georg Cantor ( )

12. Javan toistorakenteet 12.1

811120P Diskreetit rakenteet

on Abelin ryhmä kertolaskun suhteen. Tämän joukon alkioiden lukumäärää merkitään

Suurin yhteinen tekijä (s.y.t.) ja pienin yhteinen monikerta (p.y.m.)

3. Kongruenssit. 3.1 Jakojäännös ja kongruenssi

Tekijä Pitkä Matematiikka 11 ratkaisut luku 2

Johdatus lukuteoriaan Harjoitus 11 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

Johdatus lukuteoriaan Harjoitus 2 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

8.1 Murtoluvun määritelmä - murtoluvulla tarkoitetaan aina osaa (osia) jostakin kokonaisuudesta

ja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2

Analyysi III. Jari Taskinen. 28. syyskuuta Luku 1

Tietorakenteet (syksy 2013)

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

Ehto- ja toistolauseet

Digitaalitekniikan matematiikka Harjoitustehtäviä

a) Tutki algoritmin toimintaa syötteellä b) Listaa algoritmin kaikki mahdolliset tulosteet.

Ohjelmoinnin perusteet Y Python

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

Matematiikan tukikurssi, kurssikerta 5

Ohjelmoinnin peruskurssi Y1

Jäännösluokat. Alkupala Aiemmin on tullut sana jäännösluokka vastaan. Tarkastellaan

811120P Diskreetit rakenteet

LOGIIKKA johdantoa

2. Eukleideen algoritmi

Transkriptio:

Diskreetit rakenteet 811120P 5 op Juha Kortelainen Ari Vesanen Syksy 2016

Esipuhe Tämä moniste on pääosin Juha Kortelaisen laatima. Olen muuttanut algoritmien esitystavan ja tehnyt pieniä korjauksia. Ari Vesanen 2

Sisältö 1 Algoritmeista 5 1.1 Algoritmin käsite.......................... 5 1.2 Kontrollirakenteet.......................... 8 1.3 Muita esimerkkejä algoritmeista.................. 12 2 Lukujärjestelmät ja niiden muunnokset; lukujen aritmetiikka 15 2.1 Reaaliluvut ja kymmenjärjestelmä................. 15 2.2 Binaarijärjestelmä.......................... 16 2.3 Muuntaminen kymmenjärjestelmästä binaarijärjestelmään... 17 2.4 Oktaali- ja heksadesimaalijärjestelmät.............. 20 2.5 Aritmetiikka muissa kuin kymmenjärjestelmässsä........ 22 2.6 Lukujen esittäminen tietokoneessa................. 24 2.6.1 Kokonaislukujen esittäminen................ 24 2.6.2 Kokonaislukuaritmetiikka................. 27 2.6.3 Reaalilukujen esittäminen................. 30 2.6.4 Reaalilukuaritmetiikka................... 34 3 Logiikka (propositiokalkyyli, predikaattikalkyylin alkeet) 36 3.1 Propositiot............................. 36 3.2 Loogiset operaatiot (konnektiivit) ja totuustaulut............................. 38 3.3 Yhdistetyt propositiot ja lauselogiikan ilmaisut.......... 40 3.4 Looginen ekvivalenssi........................ 43 3.5 Logiikan lait............................. 45 3.6 Loogisesta päättelystä....................... 48 3.7 Predikaattilogiikka......................... 49 3.8 Todistusmenetelmiä......................... 54 4 Joukot, relaatiot ja funktiot 57 4.1 Johdanto............................... 57 4.2 Osajoukot, joukko-operaatiot ja Vennin diagrammit......................... 58 3

4.3 Joukon koko ja joukkojen karteesinen tulo............ 62 4.4 Joukkojen tietokone-esitys..................... 64 4.5 Relaatiot............................... 65 4.6 Funktiot ja laskenta tietokoneella................. 72 4.7 Yhdistetty funktio ja käänteisfunktio............... 75 4.8 Funktiot ohjelmointikielissä.................... 79 5 Rekursio ja induktio 81 5.1 Rekursio ja jonot.......................... 81 5.2 Todistaminen induktiolla...................... 85 5.3 Induktion yhteys rekursioon.................... 88 5.4 Lineaarinen rekursioyhtälö..................... 89 5.5 Rekursiivisesti määritellyt funktiot ja rekursiiviset algoritmit.. 94 6 Alkeislukuteoria (jaollisuus ja siihen liittyvät algoritmit) 98 6.1 Lukuteoriasta yleisesti....................... 98 6.2 Jaollisuus ja alkuluvut....................... 99 6.3 Suurin yhteinen tekijä ja Eukleideen algoritmi............................... 100 6.4 Kongruenssit............................ 105 6.4.1 Pseudosatunnaislukujen generointi............ 107 7 Kombinatoriikka (lukumäärien laskeminen) 111 7.1 Kombinatoriikka ja laskenta tietokeoneella............ 111 7.2 Summa- ja erotusperiaate..................... 111 7.3 Tuloperiaate............................. 112 7.4 Permutaatiot............................ 113 7.5 Kombinaatiot............................ 114 7.6 Sovellus: Otos palautuksella.................... 116 7.7 Laatikkoperiaate.......................... 118 8 Verkkoteoriaa 119 8.1 Verkkoteorian peruskäsitteet.................... 119 8.2 Verkon matriisiesitys........................ 122 8.3 Verkkojen isomora......................... 122 8.4 Eulerin polut............................ 122 8.5 Hamiltonin polut.......................... 124 8.6 Puut................................. 125 8.7 Virittävät puut........................... 128 8.8 Juurelliset puut........................... 129 4

1 Algoritmeista Algoritmin laatiminen on olennainen osa tietokoneohjelmointia. Tässä luvussa perehdytään algoritmin käsitteeseen ja esitellään merkintätapa, jolla algoritmeja voidaan esittää. 1.1 Algoritmin käsite Keskeinen tehtävä laskennassa (joko käsin tai tietokoneella suoritetussa) on sellaisen prosessin suunnittelu, joka suorittaa annetun tehtävän. Tämä tehtävä voi olla esimerkiksi nimien järjestäminen aakkosjärjestykseen; laskentalaitteiden kytkeminen verkkoon mahdollisimman edullisesti; luvun esityksen muuttaminen kantajärjestelmästä toiseen; viestin salaaminen; digitaalisen piirin suunnittelu mikrosiruun; tai robottikäden liikkeen optimointi. Jokaisessa edellä esitetyssä esimerkkitapauksissa ihminen ja/tai tietokone kykenee suorittamaan tehtävän äärellistä ohjejoukkoa käyttäen askelittain ja yksikäsitteisesti; kyse on algoritmisesta toiminnasta. Esimerkki algoritmista: (käteis)automaatin käyttö. 1. Sujauta pankkikorttisi sille varattuun aukkoon. 2. Kirjoita tunnuslukusi (PIN), kun sitä kysytään. 3. Valitse vaihtoehto 'käteisnosto' valikosta. 4. Kirjoita summa, jonka haluat nostaa. 5. Valitse jompikumpi vaihtoehtoisista kirjaustapahtumista: 'näytölle', 'kuitille'. 6. Ota korttisi ja nostamasi summa. 7. Jos olit valinnut kohdassa 5 vaihtoehdon 'kuitille', ota kuitti. 5

Edellä askeleet 1 7 muodostavat ohjejonon, joka voidaan suorittaa peräjälkeen. Kukin ohje on verrattain selkeä ja yksikäsitteinen, joten keskivertoihminen kykenee ohjeita noudattamaan. Lisäksi prosessi pysähtyy äärellisen askelmäärän jälkeen. Olemme kuvanneet algoritmin olennaisia piirteitä. Algoritmilla on mm. seuraavanlaisia ominaisuuksia. 1. Algoritmi annetaan äärellisenä ohjejoukkona (jotain merkintäjärjestelmää/kieltä käyttäen). 2. On olemassa toteuttaja (esimerkiksi ihminen tai kone), joka pystyy seuraamaan ohjeita ja suorittamaan tarvittavat toimenpiteet. 3. On olemassa välineet tiedon tuottamiseen, tallentamiseen ja käyttöönottoon. 4. Algoritmi käsittelee aina tietoa (syöte) ja tulostaa tietoa (tuloste). Toteuttaja reagoi ohjeisiin siten, että millä tahansa sovittua muotoa olevalla syötteellä toimenpiteet ovat yksinkertaisia ja ne suoritetaan askelittain. 5. Algoritmin toimenpiteet suoritetaan deterministisesti. Samalla syötteellä saadaan siten aina sama tulostus. 6. Syötteen tulee olla sovittua muotoa ja äärellisesti määriteltävissä. Syötteen koolla ei kuitenkaan ole kiinteää ylärajaa. 7. Tiedon tallentamiseen käytettävän muistitilan koko on äärellinen, mutta ei kiinteä. Muistitilan määrää ei siten ole rajoitettu. 8. Jokaisella sovittua muotoa olevalla syötteellä algoritmi pysähtyy äärellisen askelmäärän jälkeen. 9. Jokaisella sovittua muotoa olevalla syötteellä algoritmi joko ei tulosta mitään tai antaa äärellisen, yksikäsitteisen ja hyvin määritellyn tulosteen. Järjestelmää, joka toteuttaa yllä asetetut ehdot kohtia 8 ja 9 mahdollisesti lukuunottamatta, kutsutaan semialgoritmiksi. On siis mahdollista, että semialgoritmi (vaikka syöte olisi sovittua muotoakin) ei pysähdy äärellisessä askelmäärässä ja sen toiminta voi periaatteessa jatkua rajattomiin. Semialgoritmin ottamien askelten (ja sen suorittamien toimenpiteiden) lukumäärä on tällöin ääretön. Tietysti tulostekin voi tälläin olla äärettömän pituinen. Samalla syötteellä semialgoritmin on kuitenkin aina tuotettava sama tulostus. Syötteen ja (mahdollisen) tulostuksen välillä on siten funktionaalinen riippuvuus. 6

Algoritmi muistuttaa selvästi tietokoneohjelmaa. Tietokoneohjelma onkin algoritmin toteutus jollakin ohjelmointikielellä. Käytämme tässä termiä 'ohjelmointikieli' ei ainoastaan monikäyttöön tarkoitetuista kielistä kuten Pascal, Java, C ja C++, vaan myös erikoiskielistä, kuten makrokäskyjä sisältävistä taulukkolaskenta- ja tietokantakielistä. Algoritmin suunnittelu on yksi askel ohjelmien kirjoittamisessa. Tästä eteenpäin käsittelemme pääosin sellaisia algoritmeja, jotka voidaan toteuttaa tietokoneella. Jotta algoritmien suunnittelu voitaisiin eriyttää jollakin erityisellä kielellä ohjelmoinnista. Kirjoitamme algoritmit pseudokoodia (eli pseudokieltä) käyttäen. Pseudokoodi on strukturoitua suomea (ja englantia) ja se sallii meidän keskittyä algoritmin rakenteeseen ilman että meidän täytyisi muistaa jonkin ohjelmointikielen yksityiskohtia. Esim. 1. Kirjoita algoritmi, joka laskee ympyrän pinta-alan, kun ympyrän säde on annettu. Ratkaisu. Muistetaaan, että r-säteisen ympyrän pinta-ala on π r 2. Algoritmi on seuraavanlainen: Input: Reaaliluku r Output: r-säteisen ympyrän pinta-ala ALA(r) 1. ala = π *r*r 2. return ala Algoritmin otsikossa annetaan algoritmin syöte (Input) ja tulostus (Output). Jälkimmäinen tarkoittaa joko algoritmin paluuarvoa tai muuten sen suorittamisen tulosta. Lisäksi annetaan algoritmin nimi ja parametrilista, jotta sitä voidaan kutsua. Edellisessä esimerkissä algoritmia voitaisiin kutsua esimerkiksi ALA( 1.0), jolloin se palauttaisi 1.0-säteisen ympyrän pinta-alan. Esimerkissä 1 esiintyy myös muita rakenteita, joita käytetään, kun kirjoitetaan algoritmeja pseudokoodilla: askeleet numeroidaan, jotta niihin viittaminen olisi helppoa. Selittäviä tekstejä, jotka eivät suoritukseen kuulu voidaan lisätä kommenttimerkeissä // tai /* */ askelten tekstiin. Näistä // tarkoittaa rivin lopun olevan kommenttia ja merkkien /* ja */ välissä sijaitsevan tekstin olevan kommenttia. Symboli = tarkoittaa sijoituslauseketta; siten askeleessa 1 lausekkeen π r 2 arvo määritetään ja tulos sijoitetaan muuttujan ala arvoksi. Tämä arvo annetaan algoritmin kutsujalle paluuarvona, kun algoritmin suoritus päättyy. Huomaa, että matematiikan kaavat voidaan kirjoittaa matemaattisin merkinnöin, joten meidän ei tarvitse huolehtia siitä miten kaavan yksityiskohdat kirjoitettaisiin ohjelmointikielellä. Tämä koskee edellä symbolia π, jolle ei yleensä ole 7

ohjelmointikielessä omaa merkintää. Laskennan esittämiseen konkreettisesti eri ohjelmointikielillä perehdytään ohjelmoinnin kursseissa. 1.2 Kontrollirakenteet Esimerkin 1 algoritmissa askeleet suoritetaan järjestyksessä peräperään. Tavallisesti algoritmit sisältävät kuitenkin kontrollirakenteita, ohjeita, jotka määrittävät kuinka monta kertaa ja/tai millä ehdoilla käskyjä suoritetaan. Itse asiassa nämä kontrollirakenteet (muistin käytöllä terästettynä) aiheuttavat sen, että tietokoneet eroavat laskentakapasiteetiltaan tavanomaisista aritmeettisista laskukoneista. Esim. 2. Kirjoita algoritmi, joka annetusta äärellisestä reaalilukujonosta määrittää sen pienimmän alkion. Ratkaisu. Algoritmin idea: tarkastellaan kutakin jonon lukua erikseen ja pidetään kussakin askeleessa kirjaa siihen asti pienimmästä. Kun lukujono on käyty läpi, tiedetään koko jonon pienin arvo. Merkitään käsiteltävää lukujonoa ikään kuin taulukkona X[1,.., n], jolloin jonon luvut ovat X[1], X[2],..., X[n]. Siten jonon i:s luku on X[i], kun i on jokin kokonaisluku väliltä [1, n]. Input: Reaalilukutaulukko X[1,..,n], n>=1 Output: Taulukon X pienin luku MINIMI(X) 1. min = X[1] 2. for i=2 to n do 3. if X[i] < min then 4. min = X[i] 5. return min Esimerkin 2 algoritmissa esiintyy kaksi kontrollirakennetta: fordo ja ifthen. Näistä ifthen määrittelee ehtolauseen: mikäli avainsanaa if seuraava ehto on tosi, sen jälkeen tulevat sisennetyt lauseet suoritetaan. Ellei ehto ole tosi, ohjelman suoritusta jatketaan lauseesta, joka on sisennetty samalle tasolle kuin if. Käyttämässämme pseudokielessä ilmaistaan kontrollirakenteiden rajat sisennyksellä edellä mainittuun tapaan. Näin ollen kontrollirakenteessa sisennettyjä lauseita käsitellään ikään kuin yhtenä lauseena, jota myös nimitetään yhdistetyksi lauseeksi. Kontrollirakenne fordo määrittelee määrätyn toistolauseen: rivejä 3 ja 4 suoritetaan muuttujan i peräkkäisillä arvolla alkaen arvosta 2 ja päättyen ar- 8

voon n. Näin ollen rivien muodostamassa silmukassa verrataan kaikkia taulukon alkioita ensimmäistä lukuunottamatta muuttujan min arvoon. Jos taulukon alkio on tätä pienempi, muuttujan arvo päivitetään. Lopuksi muuttujan arvo on siten pienin taulukon alkioista. Alla olevassa taulukossa listataan tärkeimmät pseudokoodeissamme esiintyvät kontrollirakenteet. Kontrollirakenteet Kontrollirakenne ifthen ifthenelse fordo whiledo dowhile Esimerkki käytöstä if x<0 then x=-x if x >= 0 then y=x else y=-x sum=0 for i=1 to 10 do sum=sum+1 answer='q' while (answer!= 'y' and answer!= 'n') do print 'Vastaa y tai n' read answer do print 'Vastaa y tai n' read answer while (answer!= 'y' and answer!= 'n') Pseudokoodissa esiintyvät muuttujat ovat tavanomaisia matemaattisia muuttujia, jotka voidaan nimetä ja varustaa tarvittaessa alaindekseillä. Pseudokoodin laskuoperaatioita ovat normaalit aritmeettiset laskutoimitukset (esim. yhteen-, vähennys-, kerto- ja jakolasku), joita sovelletaan muuttujiin ja (reaaliluku)vakioihin. Myös tavanomaisia funktioita (esim. potenssiin korotus, juurenotto, eksponentti- ja logaritmifunktiot sekä trigonometriset funktiot) voidaan käyttää. 9

Pseudokielen ehdot ovat muuttujista ja vakioista (ja joskus jopa metakielen sanoista) muodostettuja väittämiä, joiden totuusarvo on aina joko tosi tai epätosi ja joiden todenperäisyys voidaan testata. Lausekkeissa tarvitaan usein seuraavia operaattoreita: operaattori tarkoitus == Vertailee yhtäsuuruutta, esim. x==5 on tosi, jos muuttujan x arvo on 5.!= Vertailee epäsuuruutta, esim. x!=5 on tosi, jos muuttujan x arvo ei ole 5. < Aidosti pienempi, esim. x<5 on tosi, jos muuttujan x arvo pienempi kuin 5. <= Pienempi tai yhtäsuuri, esim. x<=5 on tosi, jos muuttujan x arvo pienempi tai yhtäsuuri kuin 5. > Aidosti suurempi, esim. x>5 on tosi, jos muuttujan x arvo suurempi kuin 5. >= Suurempi tai yhtäsuuri, esim. x>=5 on tosi, jos muuttujan x arvo suurempi tai yhtäsuuri kuin 5. Pseudokielen lauseita ovat, syöttölauseiden (read) ja tulostuslauseiden (print) lisäksi, muiden muassa sijoituslause ja edellä mainitut kontrollilauseet. Näiden muoto ja merkitys on kuvattu seuraavassa. Sijoituslause on muotoa x = q oleva rakenne, missä x on muuttuja ja q voi olla vakio tai muuttuja tai vakioista ja muuttujista aritmeettisia operaatioita ja/tai perusfunktioita käyttäen muodostettu lauseke. Sijoituslauseen suorittamisen jälkeen muuttujan x arvo on sama kuin lausekkeen q arvo. Ehtolause if-then on muotoa if C then S oleva rakenne, missä C on ehto ja S mikä tahansa pseudokielen lause. Jos C on voimassa, suoritetaan S. Jos C ei ole voimassa, ei tehdä mitään ja lause katsotaan suoritetuksi. Edellä S voi olla useammasta lauseesta muodostettu yhdistetty lause. Ehtolause if-then-else on muotoa if C then S 1 else S 2 oleva rakenne, missä C on ehto ja S 1 sekä S 2 mitä tahansa pseudokoodilauseita. Jos C on voimassa, suoritetaan S 1, ellei, suoritetaan S 2. Tämän jälkeen lauseke on suoritettu. Edellä S 1 ja S 2 voivat olla useammasta lauseesta muodostettuja yhdistettyjä lauseita. 10

Määrätyssä toistolauseessa for i = a to b do S on i (indeksi)muuttuja, a ja b kokonaislukuvakioita ja S lause. Jos a b, lause S suoritetaan peräkkäin i:n arvoilla a, a + 1,..., b. Jos a > b, ei tehdä mitään ja lause katsotaan suoritetuksi. Toistolauseessa while C do S on C ehto ja S lause. Jos C on voimassa, lause S suoritetaan ja siirrytään toistolauseen alkuun. Jos C ei ole voimassa, ei tehdä mitään ja toistolause katsotaan suoritetuksi. Täten lauseen S suorittaminen toistuu niin kauan kuin ehto C on voimassa. Edellä S voi olla useammasta lauseesta muodostettu yhdistetty lause. Huomaa, että mikäli ehto C on alussa tosi, lauseen S suorituksen täytyy vaikuttaa ehdon totuusarvoon tai saadaan aikaan ikuisesti suoritettava toistorakenne. Toistolausekkeessa do S while C on S lause ja C ehto. Suoritetaan S ja testataan onko C voimassa. Jos C on voimassa, palataan toistolauseen alkuun. Jos C ei ole voimassa, toistolause on suoritettu. Siten lauseke S suoritetaan kerran ja suorittamista jatketaan kunnes ehto C ei enää ole voimassa. Edellä S voi olla useammasta lauseesta muodostettu yhdistetty lause. Tässäkin tapauksessa ehdon C ollessa alkujaan tosi, lauseen S suorituksen täytyy vaikuttaa ehdon totuusarvoon tai saadaan aikaan ikuisesti suoritettava toistorakenne. Pseudokieliohjelma suoritetaan siten, että sen lauseet suoritetaan kirjoitusjärjestyksessä. Pseudokieli kykenee tarvittaessa käsittelemään lukuja, merkkejä, äärellisiä jonoja, äärellisiä joukkoja, taulukoita, pinoja, verkkoja jne. Kun tarkastellaan algoritmia ja pyritään löytämään siitä mahdolliset virheet, on tärkeää pystyä suorittamaan algoritmia. Tämä tehdään tyypillisesti ajamalla algoritmia joillakin esimerkkisyötteillä rivi kerrallaan. Suoritetaan esimerkin 2 algoritmi esimerkkisyötteellä X = {5, 3, 7, 6} ja n = 4. Siten X[1] = 5, X[2] = 3, X[3] = 7 ja X[4] = 6. Seuraavasta taulukosta käy ilmi algoritmin kulku ja muuttujien kulloisetkin arvot: 11

rivi i X[i] min kommentti 1 - - 5 Ensimmäinen rivi, sijoitetaan taulukon ensimmäinen arvo muuttujaan min. 2 2 3 5 Silmukka alkaa. i = 2. 3 2 3 5 Verrataan taulukon arvoa muuttujaan min arvoon. Arvo pienempi. 4 2 3 3 Sijoitetaan muuttujalle min uusi arvo. 2 3 7 3 Silmukka jatkuu. i = 3. 3 3 7 3 Verrataan taulukon arvoa muuttujaan min arvoon. Arvo ei pienempi. 2 4 6 3 Silmukka jatkuu. i = 3. 3 4 6 3 Verrataan taulukon arvoa muuttujaan min arvoon. Arvo ei pienempi. Silmukka loppuu. 5 - - 3 Algoritmi loppuu ja palauttaa arvon 3. 1.3 Muita esimerkkejä algoritmeista Esim. 3. Laadi algoritmi, joka annetusta äärellisestä, n:stä merkistä c 1 c 2 c n koostuvasta merkkijonosta määrittää, koostuuko se pelkästään numeroista vai esiintyykö siinä muitakin symboleita ja tulostaa sitten asianmukaisen ilmoituksen. Ratkaisu. Käydään toistorakenteessa jonon merkit läpi (käyttäen muuttujaa i alaindeksinä). Apumuuttuja d saa arvon 1 ja keskeyttää toiston, jos kohdataan ei-numeerinen merkki. Input: Merkkijono C = c 1 c 2 c n, n >= 1 Output: Tulostus, onko merkkijonossa ainoastaan numeroita vai muitakin symboleita. TARKASTA_MERKIT(C) 1. i = 0 2. d = 0 3. while (i<n and d==0) do 4. i=i+1 5. if (c i ei ole numero) then 6. d=1 7. if d==1 then 8. print Merkkijonossa muitakin kuin numeroita 9. else 10. print Merkkijonossa vain numeroita 12

Esim. 4. Kirjoita algoritmi, joka laskee arvon lausekkeelle x n, missä x on mielivaltainen reaaliluku ja n positiivinen kokonaisluku. Tässä oletetaan, että kertolasku on käytettävissä, mutta potenssiin korotus ei ole. Ratkaisu. Ratkaisun idea: Palautettava arvo on muuttujassa, joka alustetaan arvoon 1. Toistorakenteessa kerrotaan luvulla x muuttujan arvoa n kertaa. Huomaa, että toiston voisi toteuttaa myös for-do-rakenteella. Seuraavassa on kuitenkin valittu while-do-silmukka. Input: Reaaliluku x, positiivinen kokonaisluku n Output: Luku x n POTENSSI(x,n) 1. tulos = 1 2. i = 0 3. while i<n do 4. tulos = tulos*x 5. i=i+1 6. return tulos Esim. 5. Laadi algoritmi, joka vaihtaa kahden muuttujan arvot. Ratkaisu. Input: Muuttujat x ja y Output: Muuttujien arvot vaihdetaan VAIHDA(x,y) 1. temp = x 2. x = y 3. y = temp Esim. 6. Työpaikkaan hakijoille on pidetty soveltuvuustesti, joka koostuu 30 monivalintakysymyksestä. Kullekin testiin osallistujalle on annettu yksikäsitteinen tunnisteluku. Suunnittele algoritmi, joka tulostaa osallistujat (tunnisteluvun mukaan), kunkin osallistujan saaman pistemäärän ja tiedotteen, kutsutaanko hakija haastatteluun (pistemäärä 24), asetetaanko hänet varalle (20 pistemäärä < 24) vai jääkö hakija huomiotta (pistemäärä < 20). Syöte koostuu hakijoiden lukumäärästä, hakijoiden soveltuvuustestivastauksista ja oikeista vastauksista. Ratkaisu. Seuraavassa n on hakijoiden lukumäärä. Oletetaan, että hakijoiden vastaukset tallennetaan kaksiulotteiseen taulukkoon A niin, että A[i][j] on 13

hakijan i vastaus kysymykseen j (i = 1, 2,..., n, j = 1, 2,..., 30). Oikeat vastaukset tallennetaan taulukkoon C siten, että ja C[k] on oikea vastaus kysymykseen k (k = 1, 2,..., 30). Input: Taulukot A[1..n][1..30] ja C[1..30], n>=1 Taulukossa A hakijoiden vastaukset ja taulukossa C oikeat vastaukset Output: Tulostetaan hakijan numero, pistemäärä ja status LUOKITTELE(A,C) 1. for i=1 to n do // Hakijan i pisteet 2. pist = 0 3. for j=1 to 30 do // Tarkistetaan vastaukset 4. if A[i][j] == C[j] then 5. pist = pist +1 6. if pist >= 24 then 7. print i,pist, haastatteluun 8. else if pist >= 20 then 9. print i,pist, varalle 10. else 11. print i,pist, huomiotta 14

2 Lukujärjestelmät ja niiden muunnokset; lukujen aritmetiikka Lukuja voidaan esittää usealla tavalla esim. eri kantajärjestelmissä. Tässä luvussa paneudutaan erityisesti lukujen esittämiseen tietokoneella. 2.1 Reaaliluvut ja kymmenjärjestelmä Tärkeimpiä lukujoukkoja ovat N = { 0, 1, 2,...} luonnolliset luvut N + = { 1, 2, 3,...} positiiviset kokonaisluvut Z = {..., 2, 1, 0, 1, 2,... } kokonaisluvut Q on rationaalilukujen joukko, ja R on reaalilukujen joukko. Luku on rationaaliluku, jos se voidaan esittää muodossa p, missä p Z ja q q N +. Reaaliluku, joka ei ole rationaaliluku, on irrationaaliluku. Tuttuja esimerkkejä irrationaaliluvuista ovat 2, Neperin luku e ja π. Reaaliluvut esitetään desimaalijärjestelmässä numerojonona, negatiivisen luvun edessä on miinusmerkki. Numerojono voi myös sisältää desimaalipilkun. Joidenkin lukujen desimaaliesitys on päättymätön; niitä ei voi esittää desimaalijärjestelmässä äärellisellä määrällä numeroita. Desimaalijärjestelmä on ns. paikkaan perustuva lukujärjestelmä; kullakin jonon numerolla on paikka-arvo, joka riippuu numeron sijainnista desimaalipisteeseen nähden. Desimaalipisteestä vasemmalle sijaitsevat järjestyksessä ykköset (10 0 ), kymmenet (10 1 ), sadat (10 2 ), tuhannet (10 3 ) jne... Desimaalipisteestä oikealle puolestaan järjestyksessä kymmenesosat (10 1 ), sadasosat (10 2 ), tuhannesosat (10 3 ), jne... Desimaaliluvun arvo saadaan kertomalla kukin numero paikka-arvollaan ja laskemalla näin 15

saadut luvut yhteen. Esimerkiksi 2386.75 = 2 10 3 + 3 10 2 + 8 10 1 + 6 10 0 + 7 10 1 + 5 10 2. 2.2 Binaarijärjestelmä Mitä tahansa luonnollista lukua, joka on ykköstä suurempi, voidaan käyttää paikkaan perustuvan lukujärjestelmän kantalukuna. Luvun 10 vakiintuminen kantaluvuksi todennäköisesti johtuu siitä, että ihmiset käyttivät muinoin kymmentä sormeaan laskemiseen. Esim. aikaa laskettaessa kantaluku on 60: 2 h 26 m 35 s = 2 60 2 + 26 60 1 + 35 60 0 sekuntia. Binaari- eli binäärijärjestelmässä kantaluku on 2; kun desimaalijärjestelmässä käytetään numeroja 0, 1,..., 9, binaarijärjestelmässä numerot (bitit) valitaan joukosta {0, 1}. Esimerkiksi 1101.01 2 on binaariluku, alaindeksi 2 ilmoittaa kantaluvun. Sekaannusten välttämiseksi, kanta ilmoitetaan aina, kun käytössä on muu kuin desimaalijärjestelmä. Binaariluvun (desimaali)lukuarvon laskeminen (ja samalla muuntaminen desimaalijärjestelmään) saadaan kirjoittamalla luku 'auki': 1101.01 2 = 1 2 3 + 1 2 2 + 0 2 1 + 1 2 0 + 0 2 1 + 1 2 2 = 8 + 4 + 1 + 0.25 = 13.25. Digitaalisten tietokoneiden data varastoidaan, siirretään ja muokataan sellaisten tietoelementtien virtana, joita voidaan merkitä symboleilla 0 ja 1. 16

Taulukko binaarinen desimaali binaarinen desimaali 0 0 1 1 1011 11 10 2 1100 12 11 3 1101 13 100 4 1110 14 101 5 1111 15 110 6 10000 16 111 7 10001 17 1000 8 10010 18 1001 9 10011 19 1010 10 10100 20 2.3 Muuntaminen kymmenjärjestelmästä binaarijärjestelmään Kuinka muuntaa desimaalijärjestelmän luku binaariseksi? Ei ole mikään ihme, että tehtävä voidaan hoitaa algoritmilla. Teemme seuraavat huomiot: a) parittomien luonnollisten lukujen binaariesitys päättyy numeroon 1, ja b) parillisten luonnollisten lukujen binaariesitys päättyy numeroon 0. Siispä Luonnollisen luvun binaariesityksen (binaariluvun) viimeinen numero (bitti) saadaan jakojäännöksenä, kun luku jaetaan kahdella. Tarvitsemme seuraavat Pascal-tyyppiset operaatiot: aina, kun n N, on n div 2 on se kokonaisosa, joka saadaan, kun n jaetaan kahdella ja n mod 2 se jakojäännös joka saadaan, kun n jaetaan kahdella. Selvästi Poistamalla luonnollisen luvun n binaariesityksen viimeinen bitti, saadaan luonnollisen luvun n div 2 binaariesitys. Siten luonnollisen luvun n binaariesityksen toiseksi viimeinen bitti saadaan jakojäännöksenä, kun luku n div 2 jaetaan kahdella. Prosessia toistetaan, kunnes kokonaisosaksi tulee nolla. Kirjoitetaan koko prosessi algoritmiksi: 17

Input: Luonnollinen luku n Output: Luvun n binaariesitys lopusta alkuun tulostettuna MUUNNA_BIN(n) 1. do 2. print n mod 2 3. n = n div 2 4. while n!=0 Algoritmin tulostus luetaan käänteisessä järjestyksessä lopusta alkuun. Sovelletaan menetelmää lukuun n = 6. Askel n Tulostus 1 6-2.1 6 0 2.2 3-2.1 3 1 2.2 1-2.1 1 1 2.2 0 - Siispä luvun 6 binaariesitys on (110) 2. Esim. 1. Mikä on luvun 25 binaariesitys? Ratkaisu. 2 25 12 1 6 0 3 0 1 1 0 1 Siten 25 10 = 1101 2. Huom. 1. Edellistä algoritmia sovellettaessa on yleinen virhe jättää viimeinen askel suorittamatta; algoritmi päättyy vasta, kun jaettava menee nollaksi! Tarkastellaan nyt sitä, miten desimaaliluvun murto-osa muunnetaan binaariseksi. Oletetaan, että haluamme desimaaliluvun 0.375 binaariesityksen. Koska 18

0.375 < 0.5, täytyy desimaalipilkun oikella puolella olevan bitin (eli 'puolikasbitin', jonka paikka-arvo on 1 ) olla 0. Voimme ilmaista asian toisin: puolikasbitti on 0, koska 2 0.375 on vähemmän kuin 1. Olemme kehittäneet 2 säännön: Reaaliluvun x ( 0 x < 1) binaariesityksen puolikasbitti on luvun 2 x kokonaisosa. Tarvitsemme pari uutta merkintää. x on reaaliluvun x kokonaisosa frac(x) on reaaliluvun x murto-osa Esimerkiksi 2.7 = 2 ja frac(2.7) = 0.7. Aikaisemmin tehdyn huomion nojalla kertomalla murto-osaa toistuvasti kahdella, saamme luvun murto-osan binaariesityksen. Prosessi voi olla päättymätön, joten se, kuinka montaa numeroa käytetään, kannattaa ilmoittaa etukäteen. Input: Desimaaliluvun murto-osa x, numeroiden lukumäärä d Output: Luvun x binaariesitys tulostettuna MUUNNA_MURTO_BIN(x,d) 1. print 0. 2. do 3. i = i+1 4. y = 2*x 5. print y 6. x = frac(y) 7. while (x!=0 and i!=d) Esim. 2. Mikä on luvun 0.32 binaariesitys viiden numeron tarkkuudella? Ratkaisu. 32 2 0 64 1 28 0 56 1 12 0 24 19

Tulos luetaan nyt ylhäältä alaspäin (vasemmanpuolinmaisin sarake). Saadaan 0.32 10 = 0.01010. Pyöristystä ei suoriteta. Jos desimaaliluvussa on sekä kokonais- että murto-osa, lasketaan kumpaisenkin binaariesitys erikseen ja saadut tulokset yhdistetään. Siten 25.32 10 = (1101.01 010) 2. 2.4 Oktaali- ja heksadesimaalijärjestelmät Edellisessä kappaleessa esitetyt tekniikat voidaan yleistää koskemaan myös muita kantajärjestelmiä kuin binaarista. Erityisesti kantoja 8 ja 16 käytetään laskennassa usein; syyt selviävät hetikohta. Kun käytössä on kantaluku 8 on kyse oktaalijärjestelmästä; tällöin luvut esitetään numeroiden 0, 1, 2, 3, 4, 5, 6, 7 avulla. Luvun jokaisen numeron paikkaarvo on tällöin kahdeksan potenssi. Esimerkiksi 374.2 8 = 3 8 2 + 7 8 1 + 4 8 0 + 2 8 1 = 252.25 10. Kantaluvun ollessa 16 olemme heksadesimaalijärjestelmässä ; tällöin tarvitaan 16 numeroa: numerojen 10, 11, 12, 13, 14, 15 sijasta käytetään isoja kirjaimia A, B, C, D, E, F. Siten käytössä on numerojoukko {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F }. Luvun jokaisen numeron paikka-arvo on 16:n potenssi. Esimerkiksi E9C.8 16 = 14 16 2 + 9 16 1 + 12 16 0 + 8 16 1 = 3740.5 10. Kun muunnetaan kymmenjärjestelmän lukua oktaali- taí heksadesimaalijärjestelmään, menetellään vastaavalla tavalla kuin binaaritapauksessa: luku 2 vain korvataan joko 8:lla tai 16:lla jakajana tai kertojana. Esim. 3. Muunna luku 275.4375 10 8-järjestelmään (oktaalijärjestelmään). Ratkaisu. Muunnetaan kokonaisosa. 8 275 34 3 4 2 0 4 20

Siten 275 10 = 423 8. Muunnetaan murto-osa. 4375 8 3 5000 4 0 Saadaan 0.4375 10 = 0.34 8. Yhdistetään tulokset, jolloin 275.4375 10 = 423.34 8. 16-järjestelmään (heksadesimaalijärjes- Esim. 4. Muunna luku 985.78125 10 telmään). Ratkaisu. Muunnetaan kokonaisosa. 16 985 61 9 3 13 0 3 Siten 985 10 = 3D9 16. Muunnetaan murto-osa. 78125 16 12 50000 8 0 Saadaan 0.78125 10 = 0.C8 16. Yhdistetään tulokset, jolloin 985.78125 10 = 3D9.C8 16. Olemme nähneet, että binaarijärjestelmä on luonteva laskennalle; se on järjestelmä, jota tietokoneet sisäisesti käyttävät. Mutta millä tavalla 8- ja 16- järjestelmät ovat hyödyllisiä? Binaarijärjestelmän huonoksi puoleksi voi laskea sen, että suurilla luvuilla on erittäin pitkät binaariesitykset(yli kolme kertaa pitemmät kuin desimaalijärjestelmässä. Suurten kantajärjestelmien etu on se, että luvut voidaan kirjoittaa käyttäen pienempää määrää numeroja. Kymmenjärjestelmä on epäkäytännöllinen, koska muuntaminen kantajärjestelmästä toiseen vaatii laskentakapasiteettia. Oktaali- ja heksadesimaalijärjestelmää käyttämällä vältetään pitkät numerosarjat ja lisäksi muuntaminen sujuu yksinkertaista algoritmia käyttäen. Kun muunnetaaan luku binaarijrjestelmästä 8-järjestelmään, ryhmitellään bitit kolmen pituisikksi jonoiksi molemmin puolin desimaalipistettä. Kukin kolmen bitin jono vastaa lukua 8-järjestelmässä. 21

Esim. 5. Muunna luku 10100011.10111 2 oktaalijärjestelmään. Ratkaisu. Nyt }{{} 010 2 }{{} 100 4 }{{} 011. }{{} 101 3 5 }{{} 110, joten 10100011.10111 2 = 243.56 8. 6 Muuntaminen oktaalijärjestelmästä binaariesitykseen on yhtä helppoa; kukin oktaalijärjestelmän numero korvataan 3-bittisellä binaariesityksellään. Etunollia ei saa jättää pois! Esim. 6. Muunna luku 514.7 8 binaariluvuksi. Ratkaisu. Saadaan 5 {}}{ 101 1 {}}{ 001 4 {}}{ 100. 7 {}}{ 111. Siispä 514.7 8 = 101001100.111 2. Muunto 2- ja 16-järjestelmien välillä on analoginen, paitsi että jokaista heksadesimaalinumeroa vastaa neljä bittiä. Esim. 7. Muunna luku 10111101001.110001 2 heksadesimaaliseksi. Ratkaisu. Nyt 0101 }{{} 1110 }{{} 1001 }{{}. 1100 }{{} 0100 }{{}, joten 5 E 9 C 4 10111101001.110001 2 = 5E9.C4 16. Esim. 8. Muunna luku B2.5D6 16 binaariluvuksi. Ratkaisu. Saadaan B 2 5 {}}{{}}{{}}{{}}{{}}{ 1011 0010. 0101 1101 0110. Siispä D 6 B2.5D6 16 = 10110010.010111010110 2. Heksadesimaalijärjestelmää käytetään tavallisesti esittämään muistiosan tai binaaritiedoston sisältö (ihmiselle) luettavassa muodossa, koska jokainen tavu (joka sisältää kahdeksan bittiä) voidaan esittää kahtena heksadesimaalinumerona. 2.5 Aritmetiikka muissa kuin kymmenjärjestelmässsä Laskutoimitusten (yhteenlasku, vähentäminen, kerto- ja jakolasku) suorittaminen muissa kuin kymmenjärjestelmässä tapahtuu niitä sääntöjä noudattaen, 22

jotka jo peruskoulussa opittiin kymmenjärjestelmälle; vain yhteen- ja kertolaskutaulut ovat erilaiset. Tarkastellaan nyt sitä, miten luonnollisten lukujen yhteen- ja kertolasku tapahtuu binaarijärjestelmässä. Yhteenlaskutaulu on tällöin seuraava. + 0 1 0 0 1 1 1 10 Lukuja lasketaan yhteen allekkain, mutta vain numeroja 0 ja 1 käyttäen. Esim. 9. Laske allekkain 11011 2 + 1110 2 (= 101001 2 ). Vähennyslasku suoritetaan 'tavanomaisesti' (vastaavasti kuin kymmenjärjestelmässä). Tietokone suorittaa vähennyslaskun eri tavalla. Esim. 10. Laske allekkain 11011 2 1110 2 (= 1101 2 ). Binaarijärjestelmän kertolaskutaulu on yksinkertainen: 0 1 0 0 0 1 0 1 'Pitkä kertolasku' binaarijärjestelmässä suoritetaan oikeastaan ilman kertolaskua; kertominenhan tapahtuu nollalla tai ykkösellä. Esim. 11. Kerro allekkain 11010 2 1011 2 (= 100011110 2 ). 'Pitkä jakolasku' on sekin suoraviivainen suorittaa; tärkeää on muistaa, että murto-osa voi muodostua rajattoman pitkäksi, joten joskus täytyy päättää monenko (merkitsevän) numeron tarkkuudella vastaus annetaan. Esim. 12. Jaa jakokulmassa luku 11101 2 luvulla 101 2 kuuden merkitsevän numeron tarkkuudella. Huom. 2. Kymmenjärjestelmän eli desimaalijärjestelmän kantaluku on 10. Desimaaliluvut ovat kymmenjärjestelmään perustuva tapa esittää reaalilukuja ja niiden likiarvoja. Edellisen nojalla kokonaisluvut ovat desimaalilukuja. Mitä tarkoitetaan (desimaali)luvun merkitsevien numeroiden lukumäärällä? Sääntö on yksinkertainen: 23

(1) desimaaliluvun alussa olevia nollia ei lasketa merkitseviksi numeroiksi; (2) ilman desimaalipistettä esitetyn luvun lopussa olevia nollia ei lasketa merkitseviksi numeroiksi; ja (3) kaikki muut luvussa esiintyvät numerot ovat merkitseviä. Siten sekä luvussa 5300 että luvussa 0071 on kaksi merkitsevää numeroa, luvussa 0.0122 on kolme merkitsevää numeroa ja luvussa 0.0078550 viisi merkitsevää numeroa. Luvussa 10.0070 on kuusi merkitsevää numeroa. Edelleen luvussa 0.8200 10 4 on neljä merkitsevää numeroa, luvussa 0.820 10 4 kolme merkitsevää numeroa ja luvussa 0.82 10 4 kaksi merkitsevää numeroa. 2.6 Lukujen esittäminen tietokoneessa Edellisessä luvussa tarkasteltiin lukujen esittämistä binaarilukujärjestelmässä. Nyt käytämmme oppimiamme tekniikoita tutkiaksemme sitä, miten lukuja esitetään ja käsitellään binaarimuodossa tietokoneessa. Luvut esitetään digitaalisessa tietokoneessa tavallisesti kiinteän pituisina bittijonoina. Kokonaislukuja käsitellään eri tavalla kuin muita reaalilukuja, joten tapaukset tulee pitää erillään. Seuraavassa tarkastellaan verrattain yleisellä tasolla sitä, miten tietokoneet lukuja käsittelevät. Myös kurssissa Tietokonearkkitehtuuri perehdytään digitaalisen tiedon esitysmuotoihin tietokoneessa. 2.6.1 Kokonaislukujen esittäminen Kokonaisluvut (positiiviset, negatiiviset tai nolla) tallennetaan tietokoneessa tavujonoina, missä kukin tavu koostuu 8 bitistä. Ohjelmoija voi tavallisesti valita useammasta kokoluokasta (jotka vastaavat eri tavulukumääriä), mutta suoraan prosessorin käsittelemien kokonaislukujen koko määräytyy prosessorin suunnitteluperiaatteiden mukaan; neljä tavua on tällöin tavanomainen koko. Mukavuussyistä tarkastelemme seuraavassa kaksitavuisia kokonaislukuja, periaatteet ovat täysin samat kuin nelitavuisessa tapauksessa. Kuinka monta eri lukua voidaan tallentaa 16 bitin avulla? Koska kukin bitti voi saada kaksi 24

arvoa ( 0 tai 1), saamme (kombinatoriikan tuloperiaatteen nojalla): 2 2 2 (16 kertaa) = 2 16 = 65536 Esimerkiksi voimme tallentaa minkä tahansa luvun n, joka on välillä 32768 n 32767, asettamalla yksikäsitteisen 16 bitin jonon vastaamaan kutakin välin kokonaislukua. Muitakin arvoalueita voitaisiin käyttää (esim. 0 n 65535), mutta käyttökelpoisin on tavallisesti sellainen väli, joka sisältää suunnilleen saman määrän positiivisia ja negatiivisia lukuja. Tavanomaisin tapa esittää luku n käyttäen 16 bittiä on seuraava. 1. Ensimmäinen bitti on ns. etumerkkibitti ; se on 0, jos n on nolla tai positiivinen ja 1, jos n on negatiivinen. 2. Jos n 0, loput 15 bittiä ovat n:n binaariesitys (varustettuna etunollilla, mikäli tarpeellista). Jos n < 0, loput 15 bittiä ovat ei-negatiivisen luvun n + 32768 binaariesitys. Luvun 2 15 = 32768 lisääminen lukuun n, kun n < 0 voi äkkiseltään vaikuttaa asioiden mutkistamiselta (mikseivät esim. etumerkin jälkeiset 15 bittiä esittäisi lukua n? 1 ) Syy on se, että lisäämällä luku 32768 lukuun n, saadaan esitystapa, joka yksinkertaistaa aritmeettisten operaatioiden suorittamista, kuten myöhemmin tullaan näkemään. Itse asiassa luvun 32768 lisääminen voidaan suorittaa sen jälkeen, kun luku n on muutettu binaarimuotoon. Tämä käy ilmi seuraavasta esimerkistä. Esim. 13. Määritä (kymmenjärjestelmän) luvun 6772 kuusitoistabittinen tietokone-esitys. Ratkaisu. Muunnetaan 6772 binaarimuotoon käyttäen 15 bittiä ja etunollia tarvittaessa. Saadaan 6772 10 = 001101001110100 2. 1 Merkintä n tarkoittaa luvun n itseisarvoa, joka määritellään: { n jos n 0 n = n jos n < 0 25

Koska luvun 32768 binaariesitys on 1000000000000000 2, meidän tulee suorittaa lasku 1000000000000000 2 001101001110100 2 = 110010110001100 2. Luvun 6772 kuusitoistabittinen tietokone-esitys on siten 1110010110001100. Saamme yleisen menetelmän: 1. Kaikki nollat vähennettävän binaariluvun lopussa (oikeanpuoleisessa päässä) säilyvät nollina vastauksessa. 2. Oikeanpuolimmaisin ykkönen säilyy ykkösenä vastauksessa. 3. kaikki muut bitit muuttuvat (nolla ykköseksi ja ykkönen nollaksi). Algoritmia soveltamalla saadaan positiivisen binaariluvun kakkosen komplementti (kannan 2 suhteen). Siten luvun 001101001110100 2 kakkosen komplementti on 110010110001100 2. Ei-negatiivisen binaariluvun ykkösen komplementti saadaan vaihtamalla sen jokainen bitti säännön 0 1, 1 0 mukaan. Binaariluvun ykkösen komplementti on yhtä pienempi kuin sen kakkosen komplementti. Tarkastellaan tilannetta hiukan yleisemmin. Olkoon n kokonaisluku, jolle 1 n 2 k 1, missä k N +. Oletetaan, että n on annettu k -bittissä binaarimuodossaan. Tällöin n:n k -bittinen kakkosen komplementti on luku 2 k n kirjoitettuna k -bittisessä binaarimuodossaan. Se saadaan soveltamalla yllä kuvattuja askelia lukuun n. Huomattakoon, että edellisiä askelia 1, 2 ja 3 ei voida käyttää luvun 32768 tietokone-esityksen määrittämiseen, koska luvun 32768 esittämiseen tarvitaan 16 bittiä. Tässä tapauksessa vähennyslaskun seurauksena saadaan 15 nollaa ja luvun 32768 tietokone-esitys on siten 1000000000000000. Esim. 14. Etsi seuraavien kokonaislukujen 16-bittinen tietokone-esitysmuoto. a) 9843 b) 15728 c) 4961. Ratkaisu. a) Etumerkkibitti on 0 ja 9843 10 = 010011001110011 2 viittätoista bittiä käyttäen. Siispä 16-bittinen tietokone-esitysmuoto on 0010011001110011. b) Etumerkkibitti on 1 ja 15728 10 = 011110101110000 2 viittätoista bittiä käyttäen. Luvun 011110101110000 2 kakkosen komplementti on 100001010010 26

000 2 Siispä 16-bittinen tietokone-esitysmuoto on 1100001010010000. c) Etumerkkibitti on 1 ja 4961 10 = 001001101100001 2 viittätoista bittiä käyttäen. Luvun 001001101100001 2 kakkosen komplementti on 11011001001 1111 2 Siispä 16-bittinen tietokone-esitysmuoto on 1110110010011111. Jos tietokone käyttää neljää tavua (32 bittiä) kahden sijasta kokonaislukuja tallentaessaan, mikä tahansa luku välillä 2 31 = 21474836648 n 2 31 1 = 21474836647 voidaan yksikäsitteisesti esittää etumerkkibittiä ja 31 muuta bittiä käyttäen analogisesti kahden tavun tapauksen kanssa. Tietysti tällöin luku 32768 korvautuu luvulla 21474836648 ja kakkosen komplementti otetaan 31-bittisestä binaariluvusta 15-bittisen sijasta. 2.6.2 Kokonaislukuaritmetiikka Tarkastellaan seuraavassa sitä miten tietokone suorittaa kokonaislukjen yhteenja vähennyslaskuja. On mukavampaa käsitellä pieniä bittimääriä, paljon pienempiä kuin todelliset tietokoneet käytännössä käsittelevät. Oletetaan, että kuvitteellinen tietokoneemme tallentaa kokonaisluvun käyttäen neljää bittiä. Tällöin ainoastaan kokonaisluvut 8, 7,..., 1, 0, 1,..., 7 voidaan esittää tällä koneella. Meillä on käytössä seuraava taulukko. 27

Taulukko kokonaisluku esitysmuoto -8 1000-7 1001-6 1010-5 1011-4 1100-3 1101-2 1110-1 1111 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 Tutkimalla yllä esitettyä taulukkoa, voimme tehdä seuraavat huomiot. 1. Kun kyseessä on luku n {0, 1, 2, 3, 4, 5, 6, 7}, luvun n tietokoneesityksen viimeiset kolme bittiä muodostavat sen 3-bittisen binaariesityksen. Koska etumerkkibitti on 0, tietokone-esitys on luvun n nelibittinen binaariesitys. 2. Kun kyseessä luku n { 8, 7, 6, 5, 4, 3, 2, 1}, luvun n tietokone-esityksen viimeiset kolme bittiä muodostavat luvun n + 8 3-bittisen binaariesityksen. Koska etumerkkibitti on 1 (ja etumerkkibitin paikka-arvo on 2 3 = 8, tietokone-esitys, kun se käsitetään binaariluvuksi, on luvun n + 16 nelibittinen binaariesitys. Oletetaan nyt, että haluamme laskea yhteen kaksi lukua m ja n tällä tietokoneella. Nyt siis m, n { 8, 7,..., 6, 7}; lisäksi oletamme, että summa m + n { 8, 7,..., 6, 7}. Väitämme, että yhteenlasku voidaan suorittaa laskemalla yhteen lukujen m ja n tietokone-esitykset tavanomaisena binaariyhteenlaskuna, kun vain viidenteen sarakkeeseen mahdollisesti tuleva bitti 1 jätetään huomiotta. Luvun n tietokone-esityksen binaariarvo on joko luvun n binaariarvo tai luvun n binaariarvo +16. Siten, kun kaksi tietokone-esitystä lasketaan yhteen, 28

tuloksena on joko yhteenlaskun oikea vastaus, oikea vastaus +16 tai oikea vastaus +32. Oikealta viidennen bitin huomiottajättäminen tapauksessa, jossa se on 1, on yhtäpitävää sen kanssa, että yhteenlaskun tuloksesta vähennetään 16. Jos nyt prosessin lopussa tulos ei ole oikea, se poikkeaa oikeasta 16:n monikerralla. Nyt m, n { 8, 7,..., 6, 7}, joten tuloksen on oltava oikea, koska lukujen m ja n vaihteluväli on vähemmän kuin 16. Esim. 15. Osoita, että seuraavat yhteenlaskut tulevat oikein suoritetuiksi 4- bittisellä tietokoneella. (a) 2 + 3 (b) ( 4) + 7 (c) ( 3) + ( 4) (d) ( 6) + 5. Ratkaisu. Kirjoitetaan kukin yhteenlasku kahdella eri tavalla; kymmenjärjestelmässä ja siten, kun se tietokoneessa suoritetaan. (a) 2 + 3 = 5; 0010 2 + 0011 2 = 0101 2 (b) ( 4) + 7 = 3; 1100 2 + 0111 2 = (1)0011 2 (c) ( 3) + ( 4) = 7; 1101 2 + 1100 2 = (1)1011 2 (d) ( 6) + 5 = 1; 1010 2 + 0101 2 = 1111 2. Jos yritämme laskea yhteen kokonaislukuja, joiden summa ei kuulu sallittuun alueeseen, tulos on (tavallisesti) väärä. Esim 6 + 7 = 13 ja 0110 2 + 0111 2 = 1101 2. Tietokone tulkitsee bittijonon 1101 luvuksi 3. Tämä ylivuoto on kuitenkin suht helppo huomata. Jos nimittäin yritetään laskea yhteen kaksi (summaltaan liian suurta) positiivista lukua, vastaukseksi tulee negatiivinen luku ja ylivuoto on helppo havaita. Samoin, ynnätessä kaksi (summaltaan liian pientä) negatiivista lukua, tulos on positiivinen ja helposti havaittavissa. Jotkin softat antavat virheilmoituksen, toiset taas eivät anna. Tämän vuoksi ohjelmia kirjoitettaessa tulee tiedostaa ylivuodon mahdollisuus ja osata käsitellä näitä tilanteita. Kokonaislukujen tietokone-esityksiin perustuva vähennyslsku on suoraviivaista, kun seuraavat seikat otetaan huomioon. 1. Vähennyslasku voidaan palauttaa yhteenlaskuksi, tahtoo sanoa, a b = a + ( b). 2. Kokonaisluvun vastaluvun tietokone-esitys on kokonaisluvun kakkosen komplementti. Luvun vähentäminen voidaan siten suorittaa lisäämällä sen kakkosen komplementti. Siispä vähennyslasku muuntuu luiskeasti yhteenlaskuksi. Menetelmän etu on se, että tietokoneen ei tarvitse mikropiiristössä erikseen ylläpitää 'summaimia' ja 'vähentäjiä' (vaikkakin kakkosen komplementin laskeminen tarvitaan). 29

Esim. 16. Arvioi vähennyslaskua 5 3 nelibittisellä tietokoneella. Ratkaisu. Luvun 5 (vast. luvun 3) tietokone-esitys on 0101 (vast. 0011). Luvun 0011 2 kakkosen komplementti on 1101 2. Nyt 0101 2 +1101 2 = 10010 2. Jättämällä huomiotta vasemmanpuolimmaisen bitin 1, saamme tulokseksi tietokoneesityksen 0010, joka edustaa lukua 2. Komplementtiin perustuvaa vähennyslaskua voidaan käyttää missä tahansa kannassa. Palataan asiaan harjoituksissa. 2.6.3 Reaalilukujen esittäminen Reaalilukujen esittäminen on mutkikkaampaa kuin kokonaislukujen, ei ainoastaan tietokoneella, vaan myös kirjoitetussa muodossa. Olemme käsitelleet reaalilukujen esittämistä desimaalijärjestelmässä (kuin myös binaarijärjestelmässä) siten että numerot esiintyvät ennen ja jälkeen desimaalipilkun. Menetelmä ei sovellu tietokone-esitykseksi ei usein liioin kirjoitusesitykseksikään. Syy tähän on se, että useissa käytännön kannalta kiinnostavissa ongelmissa törmätään reaalilukuihin jotka ovat joko erittäin suuria tai erittäin pieniä ja jotka saadaan suorittamalla fyysisiä mittauksia sopivalla tarkkuudella. Likiarvon ja täysin tarkan esityksen ero on hiuksenhieno, mutta merkittävä. Maan massa ilmoitetaan usein lukuna 0.5976 10 25 kg. Huomattakoon, että 21 {}}{ lukua ei ilmoiteta muodossa 5976 00 0. Näin siksi, että em. luku on laskettu fyysisen mittaamisen perusteella ja mittaamiseen liittyy aina tietty epätarkkuus. Emme voi sanoa, että maan massa on täsmälleen 0.5976 10 25 kg, vaan ainoastaan, että se on jossakin 0.59755 10 25 kg:n ja 0.59765 10 25 kg:n välillä. Kun mittausmenetelmät tarkentuvat, arviota voidaan parantaa. Edellisessä esimerkissä käytettyä notaatiota kutsutaan eksponenttinotaatioksi ja se soveltuu erityisen hyvin sellaiseen tieteelliseen tarkasteluun, jossa luvut saadaan fyysisten mittausten perusteella. Eksponenttinotaatioon liittyy tiettyä terminologiaa. Luvussa 0.5976 10 25 on 0.5976 signikantti, 10 on kanta(luku) ja 25 on eksponentti. Jos signikantti m on välillä 0.1 m < 1, on esitys normaalimuodossa. Se, miten reaaliluvut tarkasti esitetään tietokoneessa, riippuu periaatteessa siitä, minkä tyyppisestä koneesta on kysymys. Tosin nykyään käytetään yleisimmin esitysmuotoa, jonka spesioi IEEE:n (Institute of Electrical and Electronics Engineering) standardi 754 (1985, 2008) binaariselle liukulukuaritmetii- 30

kalle. Emme toki tarkasti kuvaa tiettyä esitystapaa, vaan tyydymme yleisesti luonnehtimaan sitä miten reaalilukuja tietokoneessa tallennetaan ja manipuloidaan. Edellä kuvattu eksponentiaalinotaatio muistuttaa reaalilukujen esitystapaa tietokoneessa. Joitakin eroja kuitenkin löytyy. Tietokoneet käyttävät 2:n potensseja 10:n potenssien sijasta tietoa manipuloidessaan. Myös eksponentti tallennetaan muunnettuun muotoon, kuten tulemme näkemään. Ennenkuin reaaliluvun tietokone-esitys voidaan löytää, se täytyy ensin muuntaa binaarimuotoon ja sen jälkeen esittää normalisoidussa binaarisessa eksponenttimuodossa. Sanomme, että reaaliluku on normalisoidussa binaarisessa eksponenttimuodossa, jos se on ilmaistu muodossa ±m 2 d, missä signikantti m on binaarimuodossa ja välillä 0.1 2 m < 1 2 ja d on kokonaisluku, joka on kirjoitettu desimaalimuodossa. Kantaluku 2 on niin ikään desimaalimuodossa. Muitakin esityksiä normalisoiduksi binaariseksi eksponentiaalimuodoksi voitaisiin käyttää; normalisoinnin tarkoitus on varmistaa jokaiselle luvulle yksikäsitteinen esitystapa. Huomattakoon, että nollaa ei voida esittää normalisoidussa binaarisessa eksponentiaalimuodossa, koska m = 0 ei kuulu m:n sallittuihin arvoihin. Reaaliluvun tallennukseen tietokoneelle tavallisesti käytetään neljää tavua ( 32 bittiä) tai kahdeksaa tavua (64 bittiä) 2. Ensimmäinen bitti on etumerkkibitti, jäljelle jäävät jaetaan eksponentin ja signikantin kesken. Eksponentille varattujen bittien lukumäärä kertoo tallennettavien lukujen arvoalueen; signikantin tallennukseen käytettyjen bittien lukumäärä puolestaan tarkkuuden, jolla luvut esitetään. Kun bittien kokonaismäärä on kiinteä, on kyse aina arvoalueen ja tarkkuuden välisestä kompromissista. Normaali menettelytapa nykyaikaisessa tietokoneessa on 8 bittiä eksponentin tallennukseen ja 23 signikantille, mikäli käytetään 32-bittistä esitysmuotoa. Nykyisin yleisempää on kuitenkin käyttää 64-bittisiä liukulukuja, jolloin eksponentti vie 10 ja signikantti 53 bittiä. Tavallisesti eksponentin binaariesitystä ei sellaisenaan tallenneta, vaan muistiin pistetään luku, jota kutsutaan karakteristikaksi. Karakteristika on ei-negatiivinen kokonaisluku, joka saadaan, kun eksponenttiin lisätään eksponenttipoikkeama, luku, joka on muotoa 2 n 1 1, missä n on eksponenttia varten (ja siten karakteristikan tallentamiseen) varattujen bittien lukumäärä. Kun eksponentti 2 Mikäli molemmat formaatit ovat tietokoneella saatavilla, puhutaan neljän tavun tapauksessa yksinkertaisesta ja kahdeksan tavun tapauksessa kaksinkertaisesta tarkkuudesta 31

tallennetaan edellä kuvatulla tavalla, tietokone voi käyttää yksinkertaisempia algoritmeja reaalilukuaritmetiikkaa toteuttamaan paljolti samalla tavalla kuin kokonaislukuaritmetiikkaa yksinkertaistettiin esittämällä negatiiviset luvut kakkosen komplementtina. Oletetaan, että karakteristikan k tallentamiseen on varattu n bittiä. Karaketristika on ei-negatiivinen kokonaisluku, joten k saa arvoja: 0 2 n 1. Eksponenttia e ja karakteristikaa k sitoo yhtälö k = 2 n 1 1 + e. Siispä e saa arvoja: 0 2 n 1 + 1 2 n 1 (2 n 1 1) eli e : 2 n 1 + 1 2 n 1. Joissakin esitystavoissa (IEEE-standardi mukaanlukien) ensimmäinen signikantin bitti (joka väistämättä on 1) jätetään tallentamatta, jolloin tarkkuutta voidaan lisätä ylimääräisen bitin verran. Kaikissa meidän esimerkeisämme signikantin ensimmäinen bitti on mukana. Esim. 17. Etsi seuraavien lukujen 32-bittinen tietokone-esitys. (a) 0.11001101 2 2 5 (b) 0.110111 2 2 3 missä käytetään 8 bittiä karakteristikaan ja eksponenttipoikkeama on 2 7 1. Ratkaisu. (a) Etumerkkibitti on 0. Karakteristika on luvun 5 + 2 7 1 kahdeksanbittinen binaariesitys, joka saadaan laskemalla yhteen 2 7 :n binaariesitys 10000000 2 ja luvun 4 binaariesitys 100 2. Saadaan 10000000 2 + 100 2 = 10000100 2. Signikantti laajennetaan 23-bittiseksi nollia lisäämällä; saadaan 11001101000000000000000. Huomattakoon, että desimaalipistettä edeltävää nollaa ei tallenneta. Tietokone-esitykseksi saadaan 01000010 01100110 10000000 00000000. (b) Etumerkkibitti on 0. Karakteristika on luvun 3 + 2 7 1 kahdeksanbittinen binaariesitys, joka saadaan yksinkertaisesti laskemalla luvun 4 seitsemänbittinen kakkosen komplementti ja varustamalla tämä etumerkkinollalla. Luvun 4 seitsemänbittinen binaariesitys: 0000100 2. Luvun 0000100 2 kakkosen komplementti: 1111100 2. Karakteristika: 01111100. Tietokone-esitykseksi saadaan 001111110 01101110 00000000 00000000. Reaaliluvun tietokone-esitys voidaan siis löytää seuraavasti. 1. Muuta luku binaarimuotoon; työskentele sillä tarkkuudella, jonka signikanttiin varattujen bittien lukumäärä edellyttää: 32

2. Esitä binaariluku normalisoidussa binaarisessa eksponenttimuodossa. Huomaa, että jos luku on itseisarvoltaan pienempi kuin yksi, desimaalipistettä välittömästi seuraavat nollat (silloin kun niitä on) siirtyvät eksponenttiin ja signikantti voidaan vastaavasti laskea suuremmalla tarkkuudella. 3. Määritä karakteristika. 4. Kirjoita tietokone-esitys. Esim. 18. Etsi 32bittinen tietokone-esitys luvulle 1873.42, kun karakteristikaan käytetään 8 bittiä ja eksponenttipoikkeama on 2 7 1. Ratkaisu. Aikaisemmin esitettyjä tekniikoita käyttäen muunnetaan luku 1873.42 aluksi 23-bittiseksi binaariluvuksi. Saadaan 1873.42 10 = 11101010001.011010111000 2. Ilmoitetaan tulos normalisoidussa binaarisessa eksponenttimuodossa: 11101010001.011010111000 2 = 0.11101010001011010111000 2 11. Etumerkkibitti on 1 ja karakteristika 10001010. Tietokone-esitys on siten 11000101 01110101 00010110 10111000. Edellinen esimerkki osoittaa sen, että reaaliluvun tietokone-esitys voi olla epätarkka, koska binaarimuotoon muutettaessa lukua typistetään käytettävissä olevaan tarkkuuteen. Lisää epätarkkuuksia voi syntyä reaalilukuaritmetiikan pyöristysvirheistä. Tilanne on toinen kuin kokonaislukujen tapauksessa, jolloin lukuja tallennetaan ja käsitellään tarkasti tietokoneessa. Eräs käytännön seuraus tästä on, että reaalilukujen yhtäsuuruuden testaus sisältää riskin. Turvallisempaa on arvioida ovatko kaksi reaallilukua x ja y ovat suunnilleen yhtäsuuria testaamalla onko voimassa x y < q, missä q on pieni positiivinen luku (esim 10 6 ). Minkäkokoisia reaalilukuja tietokoneella sitten kyetään esittämään? Oletetaan, että tietokoneemme tallentaa reaaliluvut 32 bitillä, jossa 8 bittiä on varattu karakteristikalle. Tällöin eksponenttipoikkeama on 2 7 1 ja karakteristika voi saada arvoja 0:sta lukuun 2 8 1. Koska karakteristika = 2 7 1 + eksponentti, 33

voi eksponentti saada arvoja luvusta 0 (2 7 1) lukuun 2 8 1 (2 7 1) eli joukossa 127, 126,..., 127, 128. Signikantti vaihtelee luvusta 0.1 2 lukuun 1 2. Ne positiiviset luvut, joita tietokone voi esittää sijoittuvat siten välille [0.1 2 2 127, 1 2 2 128 ). Huomattakoon, että 0.1 2 2 127 0.29 10 38 ja 1 2 2 128 0.34 10 39. Sellaiset negatiiviset luvut, joiden itseisarvo on yo. välillä, voidaan niinikään esittää tietokoneella. Mikäli laskennan tuloksena saadaan luku, joka ei mainittuihin rajoihin mahdu, tapahtuu joko alivuotoa 3 tai ylivuotoa. Esim. 19. Oletetaan, että tietokone tallentaa reaalilukuja 32 bitillä, jossa 10 bittiä on varattu karakteristikalle ja eksponenttipoikkeama on 2 9 1. Arvioi aluetta, jossa posit. reaalilukuja pystytään tietokoneella esittämään. Ratkaisu. Karakteristika voi saada arvoja 0:sta lukuun 2 10 1, joten eksponentin vaihteluväli on 0 (2 9 1):stä 2 10 (2 9 1):een eli luvusta 511 lukuun 512. Siispä reaalilukuja väliltä [0.1 2 2 511, 1 2 2 512 ) voidaan esittää. Nyt log 10 2 511 = 511 log 10 2 153.8263278. Siksipä 2 511 10 153.8263278 = 10 153 10 0.8263278 0.149 10 153. Lukua 2 512 voidaan arvioida vastaavalla tavalla, jolloin saadaan, että välillä [0.75 10 154, 0.13 0.13 10 155 ) olevat luvut ovat tietokoneella esitettävissä. 2.6.4 Reaalilukuaritmetiikka Tarkastellaan seuraavassa hiukan sitä miten aritmeettisia operaatioita suoritetaan normalisoidussa eksponenttimuodossa olevilla reaaliluvuilla. Tämä antaa yleiskuvan siitä miten tietokone suorittaa reaalilukuaritmetiikkaa. Kun halutaan laskea yhteen (vast. vähentää), menetellään seuraavasti. 1. Kirjoitetaan luvut eksponenttimuodossa yhteistä eksponenttia käyttäen siten, että signikantti on pienempi kuin 1. 3 Alivuotoa tapahtuu, kun laskennan tuloksena saadaan reaaliluku, jonka itseisarvo on pienempi kuin pienin posit. luku, joka voidaan esittää. Tilanteesta riippuen voi olla tai olla olematta sopivaa arvioida alivuodon suuruutta nollalla. 34

2. Lasketaan signikantit yhteen (vastaavasti vähennetään signikantit toisistaan); saadaan vastauksen signikantti; yhteinen eksponentti on vastauksen eksponentti. 3. Normalisoidaan vastaus tarvittaessa. Kun halutaan kertoa (vast. jakaa), menetellään seuraavasti. 1. Kerrotaan (vast. jaetaan) signikantit, jolloin saadaan vastauksen signikantti. 2. Lasketaan eksponentit yhteen (vast. vähennetään eksponentit toisistaan), jolloin saadaan tuloksen eksponentti. 3. Normalisoidaan vastaus tarvittaessa. Jäljitelläksemme tapaa, jolla tietokone suorittaa laskutoimituksia, oletetaan seuraavassa, että luvun normalisoidun esityksen signikantissa numerojen lukumäärä on kiintä ja että vastauksessa signikantti aina pyöristetään lukumäärän mukaisesti. Esim. 20. Suorita laskinta käyttäen seuraavat laskutoimitukset. Oletetaan, että signikantti esitetään neljän numeron tarkkuudella. Ratkaisu. (a) 0.4932 10 3 + 0.2881 10 4 0.3096 10 4 (b) (0.2174 10 5 ) (0.1482 10 7 ) (0.9497 10 4 ) (a) 0.4932 10 3 + 0.2881 10 4 0.3096 10 4 = 0.0493 10 4 + 0.2881 10 4 0.3096 10 4 = 0.0278 10 4 = 0.2870 10 3. (b) (0.2174 10 5 ) (0.1482 10 7 ) (0.9497 10 4 ) = 0.03393 10 2 = 0.3393 10 3. 35

3 Logiikka (propositiokalkyyli, predikaattikalkyylin alkeet) Tässä luvussa tarkastelemme muodollista logiikkaa. Logiikkaa sovelletaan monella alueella tietojenkäsittelyssä, esim. (i) digitaalipiirien suunnittelussa; (ii) kontrollirakenteiden ehtoina ohjelmoinnissa; (iii) tietokantakyselyissä; (iv) asiantuntijajärjestelmien tietämyspohjaisissa ohjelmistoissa; (v) tietokonemallinnuksessa; ja (vi) formaalissa spesioinnissa. Luvu alkuosassa perehdytään propositio- ja loppuosassa predikaattilogiikkaan. 3.1 Propositiot Luvut ovat aritmetiikan perusobjekteja. Vastaavalla tavalla propositiot ovat logiikan keskeisiä rakennuspalikoita. Propositio on väittämä, joka on joko tosi (totuusarvo 1 tai T) tai epätosi (totuusarvo 0 tai F). Esimerkkejä propositioista: 'Canberra on Australian pääkaupunki'; 'Aurinko kiertää maata'; 'Isaac Newton syntyi vuonna 1642'; '5 on suurempi kuin 7'; 'Jokainen kakkosta suurempi parillinen kokonaisluku voidaan ilmaista kahden alkuluvun summana'. 36

Edellä ensimmäinen ja kolmas ovat reaalimaailmassa tosia propositioita; toinen ja neljäs taas epätosia. Tällä hetkellä ei tiedetä onko viides propositio tosi vai epätosi. Kyseessä on ns. Goldbachin väittämä. Seuraavat ilmaisut eivät ole propositioita: 'Minne menet?'; 'Tule tänne!'; 'Tämä lause on epätosi'. Ensimmäinen on kysymys, toinen käsky. Kolmas viittaa itseensä ja johtaa ristiriitaan tai paradoksiin. Jos se on tosi, sen sisältämä väittämä johtaa ristiriitaan oletuksemme kanssa. Jos se taas on epätosi, päättelemme, että se on tosi ja olemme jälleen ristiriidassa oletuksen kanssa. Tarkastellaan ilmaisuja: 'Eläirasvojen syönti ei vaikuta kolesteroliin'; 'Olut on terveellistä'; 'x<8'. Kaksi ensimmäistä ovat ainakin jossain määrin mielipidekysymyksiä; niiden totuudellisuudesta kiisteleminen ei maksa vaivaa tässä yhteydessä. Emme tule tarkastelemaaan propositioina väitteitä, joiden totuusarvo on epäselvä. Viimeinen yllä esitetyistä lausekkeista on predikaatti, väite, josta tulee propostio, kun siinä esiintyvien muuttujien arvot sopivasti kiinnitetään. Hieman tarkemmin: Predikaatti on ilmaisu, joka - sisältää yhden tai useampia muuttujia; - ei ole propositio mutta josta tulee propositio, kun siinä esiintyvien muuttujien arvot sopivasti sidotaan. Tietokoneohjelma (tai algoritmi) voi sisältää lausekkeen ' x < 8' esim. jossakin kontrollirakenteessa. Tällöin sen totuusarvo voidaan määrittää syötteen ja ohjelman sen hetkisen tilan perusteella, joten lauseketta ' x < 8' voidaan kohdella propositiona. 37

3.2 Loogiset operaatiot (konnektiivit) ja totuustaulut Logiikassa ei olla kiinnostuneita edellä tarkasteltujen propositioiden (kuten 'Canberra on Australian pääkaupunki') totuusarvosta. Tarvitaan yleisempi näkökulma. Tarkastellaan nyt propositiota 'Jos Anna ja Pekko eivät molemmat ole onnellisia, niin joko Anna ei ole onnellinen tai Pekko ei ole onnelllinen'. Voidaksemme päätellä, että yo. propositio on tosi, meidän ei tarvitse tietää onko Anna tai Pekko onnellinen. Hetken tuumauksen jälkeen havaitsemme, että se on tosi loogisen rakenteensa perusteella. Mikä tahansa ilmaisu, jolla on sama looginen rakenne on tosi. Esimerkiksi 'Jos luvut a ja ja b eivät molemmat ole rationaalilukuja, niin joko a ei ole rationaaliluku tai b ei ole rationaaliluku'. Propositiologiikassa ollaan kiinnostuneita propositioiden rakenteesta. Em. propositiot ovat yhdistettyjä propositioita, jotka muodostetaan atomisista propositioista käyttämällä loogisia operaatioita eli konnektiiveja. Logiikan konnektiivit vastaavat algebran laskutoimituksia. (Atomisia) propositioita kuvataan propositiomuuttujien avulla; merkitsemme propositiomuuttujia pienillä kirjaimilla p, q ja r mahdollisesti alaindeksillä varustettuna. Käytössämme on viisi konnektiivia seuraavan taulukon mukaisesti: Konnektiivi ja (konjunktio) tai (disjunktio) Taulukko Symboli ei (negaatio) jos-niin (implikaatio) jos-ja-vain-jos (ekvivalenssi) Yllä esitetyt konnektiivit, negaatiota lukuunottamatta, ovat kaksipaikkaisia, eli ne kohdistuvat kahteen propostioon. Kaksipaikkainen konnektiivi asetetaan propositioiden väliin. Jos esimerkiksi p tarkoittaa propositiota 'Tänään on maanantai' ja q propositiota 'Sataa vettä', tarkoittaa p q propositiota 'Tänään on maanantai ja sataa vettä'. Negaatio asetetaan proposition eteen. 38

Niinpä p tarkoittaa propositiota 'Tänään ei sada vettä'. Loogisten konnektiivien määrittlyyn käytetään totuustauluja, joissa propositiomuuttujat saavat kaikki mahdolliset arvot. Loogisen operaation ja ( ) totuustaulu on: p q p q T T T T F F F T F F F F Tietysti konnektiivin totuustaulu heijastelee jokapäiväistä käsitystämme siitä mitä ja tarkoittaa: propositio p q on tosi jos sekä p että q ovat tosia ja se on epätosi kaikilla muilla p:n ja q :n totuusarvoilla. Sanaa tai käytetään suomen kielessä kahdessa merkityksessä. Jos tarjolla on teetä tai kahvia, kohteen oletetaan valitsevan jomman kumman, mutta ei molempia vaihtoehtoja; kysymyksessä on tällöin eksklusiivinen tai, vain toinen vaihtoehto tulee kysymykseen. Jos taas alennusta tarjotaan opiskelijoille tai eläkeläisille, henkilö, joka on molempia, saanee alennuksen; tällöin olemme tekemisissä inklusiivisen tain kanssa. Logiikassa symboli merkitsee aina inklusiivista tai -tulkintaa. Operaation totuustaulu on siten: p q p q T T T T F T F T T F F F Operaation ei (negaatio, ) totuustaulu on suoraviivainen: p p T F F T Tarkastellaan jos-niin -konnektiivia. Tarkastellaan lausetta 'Jos tupakoin säännollisesti, terveyteni huononee'. Lienemme yhtä mieltä siitä, että mikäli on totta, että henkilö tupakoi, on myös totta, että hän vaarantaa terveytensä. Siten (yleisesti) T T -tyyppinen väittamä on tosi. Mitä tapahtuu, jos henkilö ei tupakoi (eli väittämä, että henkilö tupakoi, on epätosi). Onko totta, että hänen terveytensä kärsii? Lautamiesjärki sanoo, että hänen terveytensä voi joko 39

kärsiä (mahdollisesti jostain muusta syystä kuin tupakoinnista) tai sitten ei. Siispä tyyppiä F T ja F F olevia voidaan molempia pitää totena. Ainoastaan väittämä 'Jos tupakoin säännöllisesti, terveyteni ei kärsi' (eli tyyppiä T F) on selvästi epätosi. Edellisen nojalla annamme implikaatiolle seuraavan määritelmän. p q p q T T T T F F F T T F F T Huom. 1. On tärkeää ymmärtää konnnektiivin jos-niin ja algoritmeissa esiintyvän kontrollirakenteen if-then ero; jälkimmäisessä ehtoa seuraa käsky, ei propositio. Väite p q on tosi täsmälleen silloin, kun propositioilla p ja q on samat totuusarvot: p q p q T T T T F F F T F F F T Esim. propositio 'Linnuilla on kolme jalkaa' 2 + 2 = 5 on tosi koska siinä esiintyvät propositiot ovat molemmat epätosia. 3.3 Yhdistetyt propositiot ja lauselogiikan ilmaisut Tarkastellaan seuraavassa yhdistettyjä propositioita symbolimuodossa. Esim. 1. Esitä seuraava propositio symbolisessa muodossa. 'Joko tietokoneohjelmani toimii ja siinä ei ole virheitä tai tietokoneohjelmani sisältää virheitä'. 40

Ratkaisu. Olkoon p propositio: 'Tietokoneohjelmani toimii' ja q propositio 'Tietokoneohjelmani sisältää virheitä'. Tällöin propositio 'Joko tietokoneohjelmani toimii ja siinä ei ole virheitä tai tietokoneohjelmani sisältää virheitä' on symbolisessa muodossa: (p q) q. Huomaa, miten edellisessä propositiossa sulkumerkkejä käytetään propositioiden ryhmittelyyn. Sukumerkit ovat tärkeitä: propositio p ( q q) tarkoittaa 'Tietokoneohjelmani toimii ja joko se ei sisällä virheitä tai se sisältää virheitä'. Sulkumerkkejä tulee käyttää aina, kun väärinymmärtämisen mahdollisuus on olemassa. Teemme seuraavan sopimuksen: konnektiivien vaikutusalueet kasvavassa järjestyksessä ovat:, ja,,. Operaatiot ja ovat vaikutusalueeltaan yhtä vahvat. Täten propositio tarkoittaa propositiota p q r s p r {[( p) q] r} [(s p) ( r)]. Yhdistelemällä propositiomuuttujia konnektiiveja käyttäen, saamme lauselogiikan ilmaisuja, joita myös loogisiksi ilmaisuiksi kutsutaan. Lauselogiikan ilmaisuista tulee (varsinaisia) propositioita vasta, kun korvaamme propositiomuuttujat propositioilla. Meidän mielenkiintomme kohdistuu lauselogiikan ilmaisujen rakenteen tutkimiseen. Esim. lauselogiikan ilmaisu (p q) q voidaan esittää ilmaisupuuna, kts. Kuva 3.1. Ilmaisun (p q) q totuusarvo kullakin p:n ja q :n totuusarvojen kombinaatiolla saadaan konstruoimalla totuustaulu. Esim. 2. Laadi ilmaisun (p q) q totuustaulu. Ratkaisu. Ratkaisu on esitetty alla olevassa taulukossa; kaksi ensimmäistä saraketta sisältävät muuttujien p ja q kaikki mahdolliset arvot; tämän jälkeen ilmaisun (p q) q totuustaulu rakennetaan ilmaisujen q ja p q totuustaulujen avulla konnektiivien määritelmiä käyttäen. p q q p q (p q) q T T F F T T F T T T F T F F T F F T F F 41

q p q Kuva 3.1: Ilmaisupuu Mikäli lauselogiikan ilmaisu sisältää kolme (vast. 4, 5,..., n,...) muuttujaa, on sen totuustaulussa kahdeksan (vast. 2 4, 2 5,..., 2 n,...) riviä. Tarkastellaan uudemman kerran propositiota 'Jos Anna ja Pekko eivät molemmat ole onnellisia, niin joko Anna ei ole onnellinen tai Pekko ei ole onnelllinen'. Olkoon p : 'Anna on onnellinen' ja q : 'Pekko on onnellinen' ja ilmaistaan yo. propositio symbolisesti: (p q) ( p q). Ilmaisun totuustaulu on p q p q (p q) p q p q (p q) ( p q) T T T F F F F T T F F T F T T T F T F T T F T T F F F T T T T T Havaitaan, että totuustaulun viimeinen sarake sisältää vain totuusarvoa T ; 42

siten ilmaisu (p q) ( p q) on aina tosi, riippumatta p:n ja q :n arvoista. Lauselogiikan ilmaisu, joka on aina tosi, on tautologia. Tarkastellaan nyt propositiota 'On tuulista ja sataa ja ei sada '. Tietämättä säästä mitään, ymmärrämme, että tämä propositio on epätosi rakenteensa vuoksi. Varmistutaan asiasta esittämällä propositio symbolisessa muodossa ja konstruoimalla sen totuustaulu. p q p q p (p q) q T T T F F T F F F F F T F T F F F F T F Ilmaisua, joka on siinä esiintyvien propositiomuuttujien arvoista riippumatta aina epätosi, kutsutaan ristiriidaksi. Huom. 2. Yhdistetyn proposition perusominaisuus on, että sen totuusarvo määräytyy täysin siinä esiintyvien osapropositioiden ja loogisten operaatioiden perusteella. Lauselogiikan ilmaisun totuustaulu puolestaan määräytyy täysin siinä esiintyvien propositiomuuttujien ja loogisten operaatioiden perusteella. Lauselogiikan ilmaisut voidaan induktiivisesti määritellä seuraavasti: 1. Jokainen propositiomuuttuja on lauselogiikan ilmaisu. 2. Jos p ja q ovat lauselogiikan ilmaisuja, niin p, p q, p q, p q ja p q ovat lauselogiikan ilmaisuja. 3. Ainoastaan sellaiset rakenteet, jotka saadaan sääntöjä 1 ja 2 äärellisen monta kertaa soveltamalla, ovat lauselogiikan ilmaisuja. 3.4 Looginen ekvivalenssi Seuraava propositio on aika monimutkainen: 'Ei ole totta, että syötetiedosto ja tulostetiedosto eivät kumpikaan ole tallennettuna kovalevylle'. Sama asia voidaan esittää yksinkertaisemmin propositiona: 'Joko syötetiedosto tai tulostetiedosto on tallennettuna kovalevylle'. Kun esitämme em. propositiot symbolisessa muodossa, on hyvä syy olettaa, että niiden totuuustaulut ovat samat. Merkitään propositiota 'Syötetiedosto on tallennettuna kovalevylle' symbolilla 43

p ja propositiota 'Tulostetiedosto on tallennettuna kovalevylle' symbolilla q. Laaditaan yhteinen totuustaulu: p q p q p q ( p q) (p q) T T F F F T T T F F T F T T F T T F F T T F F T T T F F Kuudes sarake on ilmaisun ( p q) ja seitsemäs sarake vastaavasti ilmaisun p q) totuustaulu. Näemme, että totuustaulut ovat samat. Kaksi samoista muuttujista koostuvaa loogista ilmaisua p ja q ovat loogisesti ekvivalentit (merk. p q ), jos ne saavat samat totuusarvot kaikilla propositiomuuttujien totuusarvojen valinnoilla. Tämä on yhtäpitävää sen kanssa, että p q on tautologia tai (vähemmän muodollisesti), että niillä on sama totuustaulu. Edelleen sanomme, että q seuraa loogisesti ilmaisusta p (merk. p q ), jos kaikilla propositiomuuttujien totuusarvojen valinnoilla siitä, että p on tosi, seuraa, että q on tosi. Tämä on yhtäpitävää sen kanssa, että ilmaisu p q on tautologia. Huomaa konnektiivin 'ekvivalenssi' ( ) ja käsitteen 'looginen ekvivalenssi' ( ) ero: p q on yksi looginen ilmaisu, joka koskee kahta loogista ilmaisua p ja q ; p q kertoo kahden loogisen ilmaisun p ja q suhteen (niiden totuustaulut ovat samat). Ilmaisun p q konversio on q p. Ilmaisun p q kontrapositio on q p. Esim. 3. Muodosta a) konversio b) kontrapositio propositiolle 'Jos 250 on tasan jaollinen luvulla 4, niin 250 on parillinen luku'. Ratkaisu. Olkoon p propositio ' 250 on tasan jaollinen luvulla 4' ja q propositio '250 on parillinen luku'. Tällöin esimerkin propositio voidaan symbolisesti esittää muodossa p q, jonka konversio on q p eli a) 'Jos 250 on parillinen luku, niin 250 on tasan jaollinen luvulla 4' ja kontrapositio q p eli b) 'Jos 250 ei ole parillinen luku, niin 250 ei ole tasan jaollinen luvulla 4'. Alkuperäinen propositio edellisessä esimerkissä pysyy totena, kun 250 korvataan millä tahansa kokonaisluvulla. Näin käy myös kontraposition suhteen. 44

Konversio sen sijaan on epätosi: luku 250 on parillinen, mutta ei tasan jaollinen luvulla 4. Esimerkistä 3 voi päätellä, että ilmaisu p q ei ole loogisesti ekvivalentti konversionsa kanssa mutta voisi olla loogisesti ekvivalentti kontrapositionsa kanssa. Varmistaudutaan asiasta laatimalla totuustaulut: p q p q q p q p q p T T T T F F T T F F T T F F F T T F F T T F F T T T T T Ilmaisuja p q ja q p vastaavat sarakkeet ovat identtiset, mutta ilmaisuja p q ja q p vastaavat sarakkeet eivät ole. 3.5 Logiikan lait Käytännössä johdutaan usein tilanteeseen, jossa on toivottavaa korvata looginen ilmaisu yksinkertaisemmalla alkuperäisen kanssa loogisesti ekvivalentilla ilmaisulla. Esim. logiikan ilmaisuja ohjelmoinnissa käytettäessä on laskutoimitusten yksinkertaistamiseksi ja virheiden välttämisesksi järkevää käyttää mahdollisimman yksinkertaisia ehtolausekkeista. Loogisesti ekvivalentteja ilmaisuja kutsutaan logiikan laeiksi. Tärkeimpiä logiikan lakeja on listattu alla olevassa taulukossa. Kaksi ensimmäistä lakia auttavat meitä poistamaan konnektiivit ekvivalenssi ( ) ja implikaatio ( ). Loput lait sisältävät vain operaatioita negaatio, disjunktio ja konjunktio. Kaksoiskieltämisen lakia lukuunottamatta säännöt esiintyvät pareittin; toinen laki saadaan ensimmäisestä korvaamalla operaatiolla ja symboli T 0 merkinnällä F 0. Tässä (ja siten alla olevassa taulukossa) T 0 tulkitaan miksi tahansa tautologiaksi ja F 0 mielivaltaiseksi ristiriidaksi. Ensimmäinen laki on aina toisen duaalilaki ja kääntäen. Lakeja on aikamoinen määrä; useat niistä ovat kuitenkin itsestäänselvyyksiä hetken tuumailun jälkeen (esim. kaksoiskieltämisen laki ja idempotenttilait). Vähemmän ilmeisien paikkansapitävyys on syytä tarkistaa totuustaulun avulla. Vielä on syytä havaita, että jotkut lait ovat lukujen algebran sääntöjen kanssa samankaltaisia, kun korvaamme pareissa (=, ), (, ), (+, ), (1, T) and (0, F) aina vasemmanpuoleisen symbolin oikeanpuoleisella. Kommutatiivisuus-, assosiatiivisuus- ja identtisyyslait ovat tällaisia ja niin on myös 1. distributii- 45

visuuslaki. Toinen distributiivisuuslaki sen sijaan ei noudata samaa kaavaa, koska algebrassa yhtäsuuruus x + (y z) = (x + y) (x + z) ei yleisesti ole voimassa. Logiikan tehtäviä ratkaistaessa tulee jokainen askel kyetä perustelemaaan logiikan lakien avulla. Laki/lait Nimi p q (p q) (q p) Ekvivalensssilaki p q p q Implikaatiolaki p p Kaksoiskieltämisen laki p p p p p p Idempotenttilait p q q p p q q p Kommutatiivisuuslait (p q) r p (q r) (p q) r p (q r) Assosiatiivisuuslait p (q r) p (q r) Distributiivisuuslait (p q) (p r) (p q) (p r) (p q) p q (p q) p q de Morganin lait p T 0 p p F 0 p Identtisyyslaki p F 0 F 0 p T 0 T 0 Annihilaatiolaki p p F 0 p p T 0 Inversiolaki p (p q) p p (p q) p Absorptiolaki Esim. 4. Todista oikeaksi 1. de Morganin laki: (p q) p q. Ratkaisu. Laki voidaan suusanallisesti esittää seuraavasti. Väittämä 'ei ole totta että p ja q ovat molemmat tosia' on yhtäpitävä väittämän 'joko p tai q on epätosi' kanssa. p q p q (p q) p q p q T T T F F F F T F F T F T T F T F T T F T F F F T T T T Koska yllä 4. ilmaisua (p q) vastaava sarake ja 7. ilmaisua p q vastaava sarake ovat samat, on 1. de Morganin laki voimassa. Esim. 5. Yksinkertaista logiikan lakien avulla ilmaisu p ( p q). 46

Ratkaisu. Koska kysymyksessä on ensimmäinen esimerkki, suoritamme yksinkertaistamisen yksityiskohtaisesti. p ( p q) p ( p q) (implikaatiolaki) p (p q) (kaksoiskieltämisen laki) p ( p q) (2. de Morganin laki) (p p) (p q) (2. distribuutiolaki) T 0 (p q) (2. inversiolaki) (p q) T 0 (1. kommutatiivisuuslaki) p q (1. identtisyyslaki) Mitä lakia kussakin tilanteessa tulisi soveltaa? Tähän kysymykseen ei ole yksiselitteistä vastausta. Tietysti konnektiivit ja (jos niitä esiintyy) on syytä poistaa kahden ensimmäisen lain avulla. Kaksi peräkkäistä negaatiota on usein (mutta ei aina) hyvä hävittää, mutta muita peukalosääntöjä on vaikea antaa. Loogisten ilmaisujen yksinkertaistaminen algoritmien ehtolausekkeissa on logiikan lakien eräs käytännön sovellus. Esim. 6. Algoritmi sisältää rivin If (x > 5 x 10) then... Miten tämä voidaan esittää yksinkertaisemmin? Ratkaisu. Ensimmäisen de Morganin lain mukaan lauseke (x > 5 x 10) on yhtäpitävä lausekkeen (x > 5) (x 10) kanssa. Tämä puolestaan on yhtäpitävä lausekkeen (x 5) (x > 10) kanssa. Siispä ohjelmarivi on yksinkertaisemmassa muodossa seuraava: If (x 5) (x > 10) then... Logiikan laeilla voidaan usein korvata totuustaulujen käyttö. Esim. 7. Osoita logiikan lakeja käyttäen, että lauseke [(p q) q] p on tautologia. 47

Ratkaisu. Jälleen yksityiskohtainen tarkastelu: [(p q) q] p [( p q) q] p (implikaatiolaki kahdesti) [ q ( p q)] p (1. kommutatiivisuuslaki) [( q p) ( q q)] p (1. distributiivisuuslaki) [( q p) (q q)] p (1. kommutatiivisuuslaki) [( q p) F 0 ] p (1. inversiolaki) [( q p)] p (2. identtisyyslaki) ( q p) p (1. de Morganin laki) (q p) p (kaksoiskieltämisen laki kahdesti) q (p p) (2. assosiatiivisuuslaki) q T 0 (2. inversiolaki) T 0 (2. annihilaatiolaki) Siispä kyseessä on tautologia. 3.6 Loogisesta päättelystä Päättely on rakenne P 1, P 2,..., P n Q, missä loogiset ilmaisut P 1, P 2,..., P n ovat oletuksia (eli premissejä) ja looginen ilmaisu Q on johtopäätös. Päättely P 1, P 2,..., P n Q on johdonmukainen (eli (loogisesti) oikea tai validi), jos looginen ilmaisu P 1 P 2 P n Q on tautologia (eli Q on looginen seuraus ilmaisusta P 1 P 2 P n. Tämä on tietysti yhtäpitävää sen kanssa, että Q on tosi, jos ilmaisut P 1, P 2,..., P n ovat tosia. Esim. 8. Intuitiivisen logiikan perusteella seuraava järkeily on tosi. 'Jos p:stä seuraa q ja q :sta seuraa r, niin p:stä seuraa r' Osoita päättely loogisesti oikeaksi. Ratkaisu. Meidän täytyy osoittaa, että päättely p q, q r p r on johdonmukainen. Edellä esitetyn nojalla riittää osoittaa, että (p q) (q r) (p r) on tautologia. Se, että näin on, käy ilmi seuraavasta totuustaulusta. 48

p q r {(p q) (q r)} (p r) T T T T T T T T T T F T F F T F T F T F F T T T T F F F F F T F F T T T T T T T F T F T F T T T F F T T T T T T F F F T T T T T 3.7 Predikaattilogiikka Propositiologiikka on hyödyllinen väline, jolla pystymme arvioimaan monentyyppisiä loogisia todisteluja. Kaikkeen se kuitenkaan ei riitä; se ei kykene käsittelemään loogisia rakenteita, joita saattaa esiintyä atomisten propositioiden sisällä. Erityisesti propositiokalkyyli ei ole riittävän vahva väline muuttujia sisältävien väitteiden käsittelyyn. Tarkastellaan seuraavia väitteitä. 'Kaikki parilliset reaaliluvut ovat kokonaislukuja. Luku 8 on parillinen reaaliluku. Siispä 8 on kokonaisluku'. 1 'Ei ole totta, että kaikki alkuluvut ovat parittomia. Siksi täytyy olla olemassa ainakin yksi parillinen alkuluku'. 2 Selvästikin molemmat edellä esitetyt väitteet ovat tosia. Kun yritämme todistaa niitä propositiologiikan avulla, ajaudumme vaikeuksiin. Olkoon p propositio 'kaikki parilliset reaaliluvut ovat kokonaislukuja', q propositio 'luku 8 on parillinen' ja r propositio 'luku 8 on kokonaisluku'. Meillä on muotoa p q r oleva väite. Ilmaisu ei ole tosi, jos p ja q ovat tosia, mutta r on epätosi. Vastaavasti merkitsemällä symbolilla p propositiota 'kaikki alkuluvut ovat pa- 1 Muunnelma klassisesta väitteestä: 'Kaikki ihmiset ovat erehtyväisiä. Sokrates on ihminen. Siispä Sokrates on erehtyväinen'. 2 Lukua 1 suurempi kokonaisluku on alkuluku, jos sen ainoat positiiviset tekijät ovat ykkönen ja luku itse. 49

rittomia' ja q :lla propositiota 'on olemassa ainakin yksi parillinen alkuluku', johdumme ilmaisuun p q, joka on epätosi, jos sekä p että q ovat tosia. Predikaattilogiikka auttaa meitä analysoimaan yllä esitetyn kaltaisia ilmaisuja. Esim. x < 5 on predikaatti; tässä x on muuttuja, joka saa reaalilukuarvoja. Jos korvaamme muuttujan x jollakin reaaliluvulla, saamme proposition, joka on joko tosi tai epätosi; esim 3 < 5 (totuusarvo T) ja 7 < 5 (totuusarvo F). Tietenkään muuttujien ei aina tarvitse olla lukuja: ' x on Oulun yliopiston opiskelija' on validi predikaatti, jossa muuttuja x saa arvoja ihmisten joukossa. Predikaatista voi saada proposition (ja tässä tulee ero propositiolaskentaan) sitomalla sen muuttujat myös muulla tavalla kuin antamalla niille kiinteät arvot. Tarkastellaan predikaattia ' x < 7 tai x > 5'. Väite on tosi kaikilla x:n reaalilukuarvoilla, joten saamme totta olevan proposition kirjoittamalla 'kaikilla x:n reaalilukuarvoilla: x < 7 tai x > 5. Jos asetamme 'kaikilla x:n reaalilukuarvoilla: x < 5, saamme proposition, joka on epätosi. Koska on olemassa reaalilukuja, jotka ovat pienempiä kuin luku 5, saamme totta olevan proposition, kun asetemme 'on olemassa sellainen reaaliluku x, että x < 5. Ilmaisut 'kaikilla' (merk. ) ja 'on olemassa' (merk. ) ovat kvanttoreita, joilla muuttuja voidaan sitoa. Esimerkiksi ilmaisussa 'kaikilla x:n reaalilukuarvoilla: x < 5, kvanttori 'kaikilla x:n reaalilukuarvoilla' sitoo muuttujan x. Predikaatissa esiintyvä muuttuja, jota ei ole sidottu, on vapaa. Käytämme seuraavassa isoja kirjaimia P, Q ja R, mahdollisesti alaindekseillä varustettuna, merkitsemään predikaatteja. Predikaattia P, joka sisältää yhden muuttujan x, merkitään P (x). Predikaattia P, joka sisältää kaksi muuttujaa x ja y, merkitään P (x, y), jne..., predikaattia, joka sisältää n eri muuttujaa x 1, x 2,..., x n, merkitään P (x 1, x 2,..., x n ). Kirjoitamme tästä lähtien x (vast. x) ilmaisun 'kaikilla x' (vast. 'on olemassa x') sijasta. Tässä on universaalikvanttori ja on eksistenssikvanttori ja Esim. 9. Kirjoita symbolisessa muodossa 'on olemassa sellainen reaaliluku x, että x < 4'. Ratkaisu. Sovimme aluksi, että muuttuja x saa arvoja reaalilukujoukossa. 50

Tämäntyyppiset olettamukset voidaan jättää kirjaamatta, kun sekaannusta ei pääse syntymään. Olkoon P (x) predikaatti x < 4. Tällöin haluttu symbolinen muoto on: x P (x). Esim. 10. Kirjoita symbolisessa muodossa 'kaikilla x:n reaalilukuarvoilla: x < 5 tai x 5. Ratkaisu. Olkoon P (x) predikaatti x < 5 ja Q(x) predikaatti x 5. Tällöin haluttu symbolinen muoto on: x[p (x) Q(x)]. Käyttämällä hyväksi sitä, että Q(x) on yhtäpitävä ilmaisun P (x) kanssa, voimme myös kitjoittaa: x[p (x) P (x)] Seuraavassa esimerkki kahden muuuttujan predikaatin käytöstä. Esim. 11. Kirjoita seuraavat propositiot symbolisessa muodossa: 'jokaista kokonaislukua x kohti on olemassa sellainen kokonaisluku y, että y = x + 1' 'on olemassa sellainen kokonaisluku y, että jokaisella kokonaisluvulla x on voimassa y = x + 1' Ratkaisu. Olkoon P (x, y) predikaatti y = x+1. Ensimmäinen propositio saa tällöin muodon x y P (x, y) ja toinen voidaan kirjoittaa y x P (x, y). On syytä tarkasti huomioida edellisen esimerkin propositioiden erot. Ensimmäisessä propositiossa (joka on tosi) luku y voi riippua luvusta x, eli se valitaan luvun x pohjalta ja muuttuu, kun x muuttuu. Toinen, epätosi propositio, edellyttää, että luku y ei riipu x:stä. Havaitsemme, että universaali- ja eksistenssikvanttorin järjestyksellä on merkitystä. Esim. 12. Tarkastellaan teatterin lipunvarausjärjestelmää. Olkoon B(h, p) predikaatti 'henkilö h on varannut paikan p'. Kirjoita seuraavat propositiot symbolisessa muodossa: a) 'paikka p on varattu' b) 'henkilö h on varannut (ainakin yhden) paikan' c) 'kaikki paikat on varattu' d) 'ainoatakaan paikkaa ei ole varannut useampi kuin yksi henkilö' 51

Ratkaisu. a) h B(h, p) b) p B(h, p) c) p h B(h, p) d) h k p [B(h, p) B(k, p) h = k]. Olisi täysin mahdollista listata universaali- ja eksistenssikvanttoreita sisältäviä logiikan lakeja (vastaavasti kuin propositiolaskennan tapauksessa); tarkastelemme kuitenkin seuraavassa vain kvanttoreiden ja sekä operaation välistä yhteyttä. Oletetaan, että haluamme soveltaa negaatiota seuraavaan propositioon: 'kaikki joutsenet ovat mustia' Voimme kirjoittaa yo proposition muodossa x P (x), missä P (x) on predikaatti: 'joutsen x on musta'. Soveltamalla negaatiota alkuperäiseen propositioon, saamme ilmaisun 'ei ole totta, että kaikki joutsenet ovat mustia' joka on yhtäpitävä ilmaisun 'kaikki joutsenet eivät ole mustia' kanssa. Negaatio voidaan muodollisesti kirjoittaa [ x P (x)]. On myös toinen tapa sanoa, että kaikki joutsenet eivät ole mustia; voimme sanoa, että täytyy olla olemassa ainakin yksi joutsen, joka ei ole musta. Siispä alkuperäisen proposition negaation kanssa yhtäpitävä propositio on 'on olemassa joutsen, joka ei ole musta', joka symbolisesti voidaan ilmasta seuraavasti: Olemme kehittäneet logiikan säännön x[ P (x)] [ x P (x)] x[ P (x)] joka sanoo, että muotoa P (x) olevan proposition negaatio saadaan vaihtamalla universaalikvanttori eksistenssikvanttoriksi ja ottamalla predikaatin negaatio. On olemassa toinen laki, jota voidaan pitää edellisen duaalilakina: [ x P (x)] x[ P (x)] 52

Laki sanoo sen, että muotoa x P (x) olevan proposition negaatio saadaan vaihtamallla eksistenssikvanttori universaalikvanttoriksi ja ottamalla predikaatin negaatio. Esim. 13. Kirjoita seuraavan proposition negaatio. 'jokaista lukua x kohti on olemassa sellainen luku y, että y < x'. Ratkaisu. Kirjoitetaan proposition negaatio symbolisessa muodossa ja sovelletaan logiikan lakeja: [ x y(y < x)] x[{ [ y(y < alx)]} x y[ (y < x)] x y(y x). Selkokielellä 'on olemassa sellainen luku x, että kaikilla luvuilla y on voimassa y x'. On tärkeää aina tarkastaa, että vastaus on järkevä, kun proposition negaatiota määritetään. Logiikan lakeja ei tule soveltaa täysin mekaanisesti. Voimme käyttää edellä esitettyjä sääntöjä todentaessamme kappaleen alussa esitetyn proposition 'Ei ole totta, että kaikki alkuluvut ovat parittomia. Siispä on olemassa ainakin yksi alkuluku, joka ei ole parillinen'. Merkitään P (x):llä predikaattia ' x on alkuluku' ja Q(x):llä predikaattia ' x on pariton'. Tällöin propositio 'kaikki alkuluvut ovat parittomia' voidaan esittää muodossa 'kaikilla x, jos x on alkuluku, se on pariton'. Symbolisessa muodossa: x[p (x) Q(x)] Alkuperäisen proposition negaatio on nyt { x[p (x) Q(x)]} Soveltamalla negaatiota koskevaa lakia ja aikaisempia propositiolaskennan sääntöjä, saamme seuraavaa: { x[p (x) Q(x)]} x{ [P (x) Q(x)]} x{ [ P (x) Q(x)]} x[ P (x) Q(x)] x[p (x) Q(x)] 53

Päättelyketjun viimeinen rivi pitää sisällään: 'On olemassa selainen x, että x on alkuluku ja se ei ole pariton'. Tämä voidaan sanoa toisin: 'On olemassa ainakin yksi alkulku, joka ei ole pariton'. Annamme vielä kaksi tärkeää predikaattikalkyylin lakia. x[p (x) Q(x)]} x[p (x) Q(x)]} x P (x) xq(x) x P (x) x Q(x) 3.8 Todistusmenetelmiä Todistamisella on keskeinen rooli matematiikassa; matematiikan teoriat perustuvat aksiomeihin, todeksi olettetuihin otaksumiin, joita ei todisteta ja jotka määrittävät kyseessä olevan teorian. Esimerkiksi Eukleideen geometrian eräs aksiomi sanoo, että kahden pisteen kautta voidaan aina piirtää suora. Aksiomien pohjalta voidaan päättelysäännöillä johtaa teoreemoja, uusia totta olevia väittämiä. Teoreeman todistus on äärellinen jono ilmaisuja, joista jokainen on joko aksiomi tai jotakin päättelysääntöä soveltamalla saatu jonon aikaisemmista ilmaisuista. Logiikan tärkeä päättelysääntö on ns. 'modus ponens' -sääntö: olkoot p ja q propositioita. Modus ponens -sääntö sanoo: 'jos p on tosi ja p q on tosi, niin q on tosi'. Matematiikan todistukset voidaan esittää hyvin formaalilla tavalla: aksiomit ja teoreemat voidaan kirjoittaa propositio- ja predikaattilogiikan merkinnöin ja päättelysääntöjä voidaan soveltaa joka askeleessa. Tällainen lähestymistapa on aiheellinen joissakin tilanteissa, esim. tietokeoneen suorittaessa mekaanista teoreemantodistamista. Tavallisesti todistukset esitetään normaalikielisinä lauseina, joissa käytetään matematiikan merkintöjä. Esittelemme seuraavassa muutamia todistustekniikoita. Eräs tärkeä menetelmä, induktiotodistus, tulee vastaan myöhemmin. Teoreemojen todistaminen on taito, joka vaatii harjoittelua. Ei ole olemassa yhtä ainoaa menetelmää, joka sopisi jokaiseen tilanteeseen, vaan usein joudutaan kokeilemaan yhden ainoan sijasta useaa todistustapaa ja eri menetelmien sekoituksia. Seuraavassa esimerkkejä. Esim. 14. Osoita, että kahden parillisen kokonaisluvun summa on aina parillinen luku. 54

Ratkaisu. Olkoot x ja y parillisia kokonaislukuja. Siis ne ovat jaollisia luvulla 2, joten x = 2m jollakin kokonaisluvuilla m ja y = 2n jollakin kokonaisluvulla n. Laskemalla summan x + y saamme x + y = 2m + 2n = 2(m + n). Koska m+n on kokonaisluku, on 2(m+n) parillinen. Siispä x+y on parillinen. Edellä esitetty ratkaisu on tyyppiesimerkki niin sanotusta suorasta todistksesta. Tällöin aloitetaan oletuksista ( x ja y parillisia) ja pidetään mielessä päämäärä, johon pyritään ( x + y on parillinen) sekä edetään sopivin väliaskelin, kunnes voidaan käyttää hyväksi parillisuuden määritelmää summaan x + y. Seuraavassa toinen esimerkki suorasta todistuksesta. Esim. 15. Osoita, että jos x on muotoa 3k + 1 (missä k on kokonaisluku) oleva luku, niin x 2 on myös tätä muotoa. Ratkaisu. Oletetaan, että x = 3k + 1, missä k on kokonaisluku. Tällöin x 2 = (3k + 1) 2 = (3k) 2 + 2 (3k) 1 + 1 2 = 9k 2 + 6k + 1 = 3(3k 2 + 2k) + 1 Asettamalla n = 3k 2 + 2k näemme, että x 2 muotoa. = 3n + 1 ja siten vaadittua Esim. 16. Olkoon x kokonaisluku. Osoita, että jos x 2 on parillinen. on parillinen, niin x Ratkaisu. Nyt suora todistus ei välttämättä johda helposti haluttuun lopputulokseen. Sovelletaan toista tekniikkaa, ns. epäsuoraa todistusta. Muistamme, että propositio p q on loogisesti ekvivalentti kontrapositionsa q p kanssa. Osoitamme oikeaksi alkuperäisen väitteen kontraposition 'Jos x on pariton, niin x 2 on pariton. Oletetaan, että x on pariton. Tällöin x = 2k + 1 missä k on jokin kokonaisluku. tällöin x 2 = (2k + 1) 2 = 4k 2 + 4k + 1 = 2(2k 2 + 2k) + 1 Asetetaan n = 2k 2 + 2k ja havaitaan, että x 2 = 2n + 1 ja pariton. Esim. 17. Olkoot x, y ja z positiivisia kokonaislukuja. Osoita, että jos xy = z 2 ja x < z, niin y > z. 55

Ratkaisu. Väite voidaan todistaa suoraankin, mutta käytetään tällä kertaa ristiriitatodistusta: tehdään vastaoletus eli oletetaan, että väite (tässä tapauksessa y > z ) ei ole tosi ja johdetaan ristiriita oletusten kanssa. Oletetaan siis, että xy = z 2 ja x < z, mutta y z. Kertomalla viimeinen epäyhtälö puolittain positiivisella kokonaisluvulla x saamme xy xz. Koska x < z, on xy < z 2. Tämä on ristiriidassa sen kanssa, että xy = z 2. Siis vastaoletus on väärä ja väite oikea. Joskus joudumme osoittamaan vääräksi yleisen, esim. kokonasilukuja koskevan väitteet. Tämä voidaan usein tehdä vastaesimerkin avulla. Esim. 18. Osoita vääräksi seuraava väite. Jokainen luonnollinen luku voidaan esittää muodossa x 2 + y 2, missä x ja y ovat luonnollisia lukuja. Ratkaisu. Osoitetaan, että 3 on vastaesimerkki. Osoitamme siis, että lukua 3 ei voida esittää kahden luonnollisen luvun x ja y neliön summana. Jos x 1 ja y 1, niin x 2 + y 2 2 < 3, joten x 2 + y 2 ei voi olla yhtäsuuri kuin 3 tässä tapauksessa. Jos sitten x 2 tai y 2, on x 2 + y 2 4, joten x 2 + y 2 ei voi olla yhtäsuuri kuin 3 tässäkään tapauksessa. Siten lukua 3 ei voi esittää kahden luonnollisen luvun neliön summana. 56

4 Joukot, relaatiot ja funktiot On väitetty, että kaikki moderni matematiikka voidaan esittää joukko-opin ja funktioiden avulla. Myös tietojenkäsittelytieteessä tämän teorian tuntemus on hyödyllistä. Tässä luvussa käsitellään joukko-opin perusteiden lisäksi asiaan läheisesti liittyviä relaatioita ja funktioita. 4.1 Johdanto Matematiikassa joukko on mikä tahansa hyvin määritelty kokoelma objekteja, joita kutsutaan joukon alkioiksi. Esimerkkejä joukoista: tälle luennolle osallistuvat opiskelijat, ASCII-merkit, luvulla viisi tasan jaolliset kokonaisluvut, jne... Joukko voidaan määrittää kahdella tavalla. Joko luettelemalla joukon alkiot ja asettemalla ne aaltosulkeiden sisään tai luonnehtimalla joukkoa jonkin ominaisuuden (predikaatin) perusteella jonka kaikki sen alkiot toteuttavat. Kymmentä pienemmät parittomat positiiviset parittomat kokonaisluvut voidaaan esittää seuraavasti: {1, 3, 5, 7, 9}. Mikäli selkeä sääntö on havaittavissa joukon alkioissa, voimme käyttää kolmea pistettä merkitsemään alkioita, joita ei luetella. Esim. lukua 50 pienempien parittomien positiivisten kokonaislukujen joukko voidaan esittää muodossa {1, 3, 5,..., 49} sen sijaan että jokainen alkio lueteltaisiin. Myös äärettömiä joukkoja voidaan esittää luettelemalla niiden alkiot. Kaikkien positiivisten parittomien kokonaislukujen joukko voidaan antaa muodossa {1, 3, 5,...}. Toinen tapa määrittää joukko käyttää ominaisuutta, jonka kaikki joukon alkiot toteuttavat. Esimerkiksi kaikkien lukua 50 pienempien parittomien positiivisten kokonaislukujen joukko voidaan esittää muodossa { n n on pariton kokonaisluku ja 0 < n < 50 }. 57

Tässä joukkomerkinnässä n kuvaa tietysti (mitä tahansa) joukon alkiota ja pystyviivan takana esitetään ominaisuus, jonka tämä (mikä tahansa) joukon alkio toteuttaa. Kun esitämme joukon muodossa {x P (x) }, missä P (x) on predikaatti, sanomme, että joukko on annettu predikaattimuodossa. Merkitsemme joukkoja isoilla kirjaimilla A, B, C,..., X, Y,... joskus alaindekseillä varustettuna. Joukon alkioita merkitään pienillä kirjaimilla a, b, c,..., x, y,.... Sitä, että alkio a kuuluu joukkoon A merkitään: a A. Jos taas alkio b ei kuulu joukkoon A, merkitään: b / A. Joukko määräytyy täysin alkioidensa kautta. Siten kaksi joukkoa A ja B ovat yhtäsuuret eli samat, merk. A = B, täsmälleen silloin, kun niillä on samat alkiot. Tyhjä joukko, merkitään, on joukko, jossa ei ole yhtään alkiota. Huomattakoon, että { } ei ole tyhjä joukko, vaan yksialkioinen joukko, jonka ainoa alkio on tyhjä joukko. Joskus on järkevää olettaa, että kaikki annetun ongelman yhteydessä käsitellyt alkiot kuuluvat kiinteään perus- eli universaalijoukkon E. Tämä joukko voi vaihdella, kun siirrytään ongelmasta toiseen. Esimerkiksi reaalilukuihin keskityttäessä on järkevää olettaa, että perusjoukko on R. 4.2 Osajoukot, joukko-operaatiot ja Vennin diagrammit Olkoot A ja B joukkoja. Sanomme, että joukko A on joukon B osajoukko, merkitään A B, jos jokainen joukon A alkio on myös B :n alkio. Usean joukon välisiä relaatioita on näppärä kuvata Vennin diagrammin avulla graa- sesti. Osajoukon määritelmän nojalla tyhjä joukko on jokaisen joukon A osajoukko: A. Koska ei sisällä yhtään alkiota, propositio x[x x A] on tosi. Edelleen joukko A on aina itsensä osajoukko: A A. Kun joukko esitetään luettelemalla sen alkiot, ei luettelujärjestyksellä joukon identiteetin kannalta ole merkitystä; siten {a, b, c} = {b, a, c}. Liioin sillä, kuinka monta kertaa alkio luettelossa esiintyy ei ole merkitystä, joten {a, b, c} = {b, a, c, a, b}. Vain sillä, mistä alkioista joukko koostuu, on väliä. Selvästi joukot A ja B ovat samat täsmälleen silloin, kun A B ja B A. Joukko A on joukon B aito osajoukko, jos A B ja A B. Selvästi joukko 58

Kuva 4.1: Joukkojen leikkaus A on joukon B aito osajoukko, täsmälleen silloin, kun A B ja on olemassa b B, jolle b / A. Kahden joukon A ja B leikkaus on joukko A B = { x x A ja x B }. Kuvassa 4.1 joukkojen leikkaus Vennin diagrammilla kuvattuna. Sanomme, että joukot A ja B ovat (pareittain) erilliset eli pistevieraat, jos A B =. Joukot ovat erilliset täsmälleen silloin, kun niissä ei ole yhteisiä alkioita. Kahden joukon A ja B unioni eli yhdiste on joukko A B = { x x A tai x B }. Joukkojen unioni saadaan yhdistämällä niiden alkiot yhdeksi joukoksi. Kuva 4.2 esittää joukkojen unioni Vennin diagrammin avulla. Kahden joukon A ja B erotus eli joukkoerotus on joukko A \ B = { x x A ja x / B }. Joukkojen A ja B erotus saadaan poistamalla A:sta kaikki joukon B alkiot. 59

Kuva 4.2: Joukkojen unioni Kvassa 4.3 on joukkojen erotus Vennin diagrammilla kuvattuna. Perusjoukon E ja joukon A erotusta kutsutaan A:n komplementiksi ja sitä merkitäään A c : A c = E \ A = { x x E ja x / A }. Joukkojen erotus on vähiten käytetty joukko-operaatio. Osittain tämä johtuu siitä, että se voidaan palauttaa komplementtiin (joka tosin yllä määriteltiin erotusta käyttäen). Myöhemmin esitettyjen joukko-opin lakien avulla on helppo osoittaa todeksi yhtäläisyys A \ B = A B c. Esim. 1. Olkoon E = {1, 2, 3,..., 10} universaalijoukko ja A = {2, 4, 7, 9}, B = {1, 4, 6, 7, 10} ja C = {3, 5, 7, 9}. Muodosta joukot a) A B b) A C c) B C c d) (A B c ) C e) (B C) c C. Käytä hyväksi Vennin diagrammeja. Ratkaisu. a) A B = {1, 2, 4, 6, 7, 9, 10} b) A C = {7, 9} c) C c = {1, 2, 4, 6, 8, 10}, joten B C c = {1, 4, 6, 10} d) B c = {2, 3, 5, 8, 9}, joten A B c = {2, 9} ja (A B c ) C = {2, 3, 5, 7, 9} e) B C = {1, 3, 4, 5, 6, 7, 9, 10}, joten (B C) c = {2, 8} ja (B C) c C =. 60

Kuva 4.3: Joukkojen erotus Joukko-opin operaatioilla leikkaus, unioni ja komplementti on luonteva vastineensa logiikan konnektiiveissa konjunktio ('ja'), disjunktio ('tai') ja negaatio ('ei'). Tämän vuoksi logiikan laeista saadaan vastaavat joukko-opin lait. Esimerkiksi logiikan kommutatiivisuuslain p q q p nojalla saamme joukkoopin kommutatiivisuuslain A B = B A. Tämä nähdään seuraavasti: A B = { x x A ja x B} = { x x B ja x A} = B A Joukko-opissa ovat voimassa samankaltaiset lait kuin propositiolaskennassa. Laki Nimi (A c ) c = A Kaksoiskomplementtilaki A A = A A A = A Idempotenttilait A B = B A A B = B A Kommutatiivisuuslait (A B) C = A (B C) (A B) C = A (B C) Assosiatiivisuuslait A (B C) = A (B C) = Distributiivisuuslait (A B) (A C) (A B) (A C) (A B) c = A c B c (A B) c = A c B c de Morganin lait A E = A A = A Identtisyyslait A = A E = E Annihilaatiolait A A c = A A c = E Inversiolait A (A B) = A A (A B) = A Absorptiolait 61

4.3 Joukon koko ja joukkojen karteesinen tulo Joukon A koko eli kardinaalisuus, merkitään A, on sen alkioiden lukumäärä. Siten äärettömän joukon C koko on ääretön; tällöin merkitään C =. Esim. 2. Joukolle A = {1, 2, 3, 5} on A = 4. Joukolle N puolestaan N =. Joukon A kaikkien osajoukkojen muodostamaa joukkoa kutsutaan A:n potenssijoukoksi ja sitä merkitään P(A). Esim. 3. Tarkastellaan kolmen alkion joukkoa A = {a, b, c}. Tällöin P(A) = {, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}. Lause 1. Äärellisellä joukolla A on 2 A eri osajoukkoa. Todistus. Olkoon A = {a 1, a 2,..., a n } joukko, jossa on n alkiota, n N. Muodostetaan (mielivaltainen) A:n osajoukko B. Voimme tehdä sen seuraavan algoritmin mukaisesti. Tarkastellaan kutakin A:n alkiota erikseen ja päätetään kuuluuko se joukkoon B vai ei. Kuuluuko alkio a 1 joukkoon B? Meillä on kaksi mahdollisuutta: joko a 1 B tai a 1 / B. Samalla tavalla joko a 2 B tai a 2 / B. Jatketaan vastaavalla tavalla alkioiden a 3, a 4,..., a n suhteen. Teemme (ns. kombinatoriikan tuloperiaatteen nojalla) johtopäätöksen, että mahdollisia osajoukkoja on 2 } 2 {{ 2 } = 2 n n kertaa kappaletta. Koska A = n, on väite tosi. Usein on tarpeen tarkastella rakenteita, joissa joukon alkioiden järjestyksellä on merkitystä. Alkioiden a 1, a 2,..., a n, missä n N +, (järjestetty) n-monikko on jono (a 1, a 2,..., a n ), missä siis alkioiden järjestyksellä on merkitystä. Erityisesti 2-monikkoa (vastaavasti 3-monikkoa) kutsutaan järjestetyksi pariksi (vastaavasti järjestetyksi kolmikoksi). Edellisen nojalla n-monikko (a 1, a 2,..., a n ) ja m-monikko (b 1, b 2,..., a m )ovat yhtäsuuret (eli samat), jos edellä n = m ja a i = b i, kun i = 1, 2,..., n. Joukkojen A ja B karteesinen tulo on joukko A B = {(a, b) a A ja b B}. 62

Sanallisesti: A B koostuu kaikista sellaisista järjestetyistä kaksikoista, joissa ensimmäinen alkio kuuluu joukkoon A ja toinen alkio joukkoon B. Yleistetään karteesisen tulon käsitettä. Olkoon n N +. Tällöin joukkojen A 1, A 2,..., A n karteesinen tulo on joukko A 1 A 2 A n = {(a 1, a 2,..., a n ) a i A i kun i = 1, 2,..., n }. Taas sanallisesti: A 1 A 2 A n koostuu kaikista sellaisista n-monikoista, joissa ensimmäinen alkio kuuluu joukkoon A 1, toinen alkio joukkoon A 2, jne..., n. alkio joukkoon A n. Voimme esittää yo karteesisen tulon hivenen ytimekkäämmin logiikan merkinnöin: A 1 A 2 A n = {(a 1, a 2,..., a n ) i {1, 2,..., n} : ai A i }. Esim. 4. Olkoon A = {a, b} ja B = {1, 2, 3}. Esitä karteesinen tulo A B luettelomuodossa. Ratkaisu. Vaadittu karteesinen tulo on A B = { (x, y) x A y B} = { (a, 1), (a, 2), (a, 3), (b, 1), (b, 2), (b, 3) }. Karteesisia tuloja sovelletaan laajasti tietokoneella laskennassa. Joissakin tietokoneissa (käyttöjärjestelmissä) käyttäjä tunnistetaan merkkijonosta, jonka kolme ensimmäistä symbolia ovat kirjaimia, kolme seuraavaa numeroita ja seitsemäs symboli taas kirjain, esim ABC123A. Olkoon L kirjainten ja D numerojen joukko. Tällöin validit merkkijonot saadaan karteesisesta tulosta L L L D D D L. Käyttäjätunnus ABC123A vastaa 7-monikkoa (A, B, C, 1, 2, 3, A) karteesisessa tulossa L L L D D D L. Merkinnöissä on pientä eroa, käsitteellisellä tasolla eroa ei ole. Toisinaan karteesinen tulo halutaan muodostaa vain yhtä joukkoa käyttäen. Joukon A (n-ulotteinen) karteesinen tulo on joukko A n = { (a 1, a 2,..., a n ) i {1, 2,..., n} : ai A }. Yllä karteesinen tulo A A A }{{} n kertaa on kirjoitettu muodossa A n. Koulusta tuttu (reaaliluku)taso R 2 siihen piirrettyine x- ja y -akseleineen on reaalilukujoukon R kaksiulotteisen karteesisen tulon geometrinen esitys. 63

4.4 Joukkojen tietokone-esitys Jotkin ohjelmointikielet (esim. Pascal) sallivat joukkojen käsittelemisen (yhdistettynä) tietorakenteena; tällöin joukon alkiot kuuluvat samaan tietotyyppiin, esim. kokonaislukuihin tai kirjoitusmerkkeihin. Näin ollen ohjelmassa joukko määritellään aina suhteessa perusjoukkoon E. Tällöin herää kysymys: miten joukkoja käsitellään ja miten niitä tallennetaan tietokoneessa? Vastaus tähän riippuu käytettävästä ohjelmointikielestä; esitystapoina käytetään mm. taulukkoja, hash-taulukkoja ja erilaisia puurakenteita. Näitä tietorakenteita käsitellään myöhemmillä kursseilla. Kun perusjoukkoon E kuuluu verrattain vähän alkioita, kätevä tapa esittää joukkoja on bittivektori, jota kuvataan seuraavassa. Kun käytetään bittivektoriesitystä, joukon E alkiot on lueteltu määrätyssä järjestyksessä ja jokainen ohjelmassa käsitelty joukko on E :n osajoukko. Joukko E on äärellinen, olkoon n joukon E koko. Tällöin (universaalijoukon E osajoukko) A tallentuu bittijonona b 1 b 2 b n, missä aina kun i {1, 2,..., n}, bitti b i = 1, jos E :n i. alkio kuuluu joukkoon A ja b i = 0, mikäli E :n i. alkio ei kuulu joukkoon A. Käsittämällä n:n pituinen bittijono b 1 b 2 b n aina joukon B n alkioksi (b 1, b 2,..., b n ), voimme olettaa, että b 1 b 2 b n B n. Edellä B = {0, 1} binaariaakkosto. Esim. 5. Olkoon E = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}. a) Mikä on joukon A = {2, 3, 5, 7} bittimuotoinen (tietokone-)esitys (eli bittijonoesitys)? b) Mikä on bittijonoa 1001011011 vastaava joukko? Ratkaisu. a) Joukon A = {2, 3, 5, 7} bittimuotoinen (tietokone-)esitys on 011101000. b) Bittijonoa 1001011011 vastaava joukko on {1, 4, 6, 7, 9, 10}. Huomattakoon, että (joukkojen) leikkaus, unioni ja komplementti voidaan suorittaa suoraan joukkojen bittimuotoisille esityksille silloin, kun joukoilla on sama perusjoukko. Esimerkiksi joukon A B bittijonoesityksessä on i. paikassa bitti 1 täsmälleen silloin, kun sekä A:n että B :n bittijonoesityksessä on i. paikasa bitti 1. Edellä A B :n bittimuotoisen esityksen löytäminen tapahtuu bittikohtaista ja-operaatiota käyttäen. Vastaavalla tavalla joukkojen A B ja A c bittijonoesitykset saadaan bittikohtaisia tai- ja ei-operaatioita käyttäen. Esim. 6. Olkoon E = {1, 2, 3, 4, 5, 6, 7, 8}. Oletetaan, että joukon A ja B bittijonoesitykset ovat vastaavasti 00101110 ja 10100101. Määritä joukkojen A B, A B ja A c bittijonoesitykset. 64

Ratkaisu. Suoritetaan bittikohtainen ja, tai ja ei ja saadaan seuraavat bittijonoesitykset A B : 00100100,. A B : 10101111ja A c : 11010001 4.5 Relaatiot Reaalimaailman ongelmia mallinnetaan ja ratkaistaan matematiikan teorioita hyväksikäyttäen; nämä ratkaisut realisoituvat usein tietokoneohjelmina. Reaalimaailman ihmisten ja esineiden välisiä suhteita vastaavat matematiikassa relaatiot, joilla on tärkeitä sovelluksia myös tietokoneella laskennassa. Matematiikassa relaatiot liittyvät aina yhteen tai useampaan joukkoon. Perusmääritelmässä relaation käsitteeseen ei sisällytetä lainkaan semantiikkaa. Olkoon n positiivinen kokonaisluku ja A 1, A 2,..., A n joukkoja. Tällöin joukkojen A 1, A 2,..., A n välinen relaatio on mikä tahansa karteesisen tulon A 1 A 2 A n osajoukko. Esim. 7. Olkoon A 1 = {0, 1}, A 2 = N ja A 3 suomalainen aakkosto. Tällöin joukko T = {(x, y, z) x = 1 y on parillinen z {a, d, r, s}} on joukkojen A 1, A 2 ja A 3 välinen relaatio. Erikoistapauksena edellä esitetystä määritelmästä saadaan seuraavaa. Joukkojen A ja B välinen (binaari)relaatio on mikä tahansa karteesisen tulon A B osajoukko. Kun R on joukon A ja B välinen binaarirelaatio, kirjoitamme usein a R b merkinnän (a, b) R sijasta. Edelleen joukon A n-ulotteinen relaatio on mikä tahansa karteesisen tulon A } A {{ A osajoukko. } n kertaa Ja vielä: joukon A binaarirelaatio on mikä tahansa karteesisen tulon A A osajoukko. 1 1 Sana binaarirelaatio viittaa tässä siihen, että suhde koskee aina kahta joukon A alkiota. 65

Esim. 8. Olkoon I kaikkien ihmisten muodostama joukko. Tällöin F = {(a, b) a on b:n lapsi} on joukon A binaarirelaatio. Vastaavasti = {(x, y) x, y R x y} on joukon R binaarirelaatio. Keskitymme seuraavassa binaarirelaatioihin. Binaarirelaatioiden ja suunnattujen verkkojen välillä on kääntäen yksikäsitteinen vastaavuus. Äärellisiä binaarirelaatioita voidaan siten kuvata graasesti. Olkoon A (äärellinen) joukko ja R sen binaarirelaatio. Kutakin joukon A alkiota vastaa suunnatussa verkossa solmu, joka voidaan piirtää mustana täplänä. Solmusta x piirretään nuoli solmuun y täsmälleen silloin, kun (x, y) R. Esim. 9. Esitä graasesti joukon A = {1, 2, 3, 4} N binaarirelaatio = {(x, y) x, y A x y}. Ratkaisu. Seuraava kuva esittää annettua relaatiota suunnattuna verkkona. Äärellinen binaarirelaatio voidaan esittää myös relaatiomatriisin avulla. Olkoon n N + ja a 1, a 2,..., a n joukon A alkiot; siis A = n. Joukon A binaarirelaation R relaatiomatriisin rivit ja sarakkeet nimetään joukon A alkioilla a 1, a 2,..., a n. Matriisin paikassa (i, j) (i. vaakarivin ja j. pystyrivin leikkauksessa on T (vast. F), jos (a i, a j ) R (vast. (a i, a j ) / R). Esim. 10. Laadi relaatiomatriisi Esimerkki 9:n binaarirelaatiolle. 66

Ratkaisu. Saamme matriisin (taulukon) 1 2 3 4 1 T T T T 2 F T T T 3 F F T T 4 F F F T Kun jatkossa puhumme relaatioista, tarkoitamme aina binaarirelaatioita. Olkoon A joukko ja R sen relaatio. Relaatio R on reeksiivinen, jos a R a aina, kun a A; irreeksiivinen, jos ei ole olemassa sellaista a A, että a R a; symmetrinen, jos siitä, että a R b seuraa, että b R a aina, kun a, b A; antisymmetrinen, jos siitä, että a R b ja b R a seuraa, että a = b aina, kun a, b A; transitiivinen, jos siitä, että a R b ja b R c seuraa, että a R c aina, kun a, b, c A. Esitetään vielä edellisen määritelmän ehdot tiukemmassa loogisessa muodossa: Olkoon A joukko ja R sen relaatio. reeksiivisyys: x[xry]; irreeksiivisyys: x[ (xrx)]; symmetrisyys: x y[xry yrx]; antisymmetrisyys: x y[xry yrx x = y]; transitiivisyys: x y z[xry yrz xrz]. Esim. 11. Seuraavat relaatiot on määritelty kaikkien ihmisten I joukossa. Luokittele relaatiot edellä annettujen relaatio-ominaisuuksien nojalla. a) R 1 = { (a, b) a on b:n sisko } b) R 2 = { (a, b) a on b:n isä } c) R 3 = { (a, b) a:lla on samat biologiset vanhemmat kuin b:llä } Ratkaisu. a) Relaatio R 1 ei ole reeksiivinen, vaan irreeksiivinen (henkilö ei voi olla itsensä sisko); se ei ole symmetrinen (jos a on tyttö ja b poika) eikä antisymmetrinen (a voi olla b:n sisar ja b puolestaan a:n sisar ilman että 67

henkilöt a ja b ovat samat. Onko R 1 transitiivinen? Ei, sillä jos a ja b ovat siskokset (siis kumpikin tyttöjä), niin ar 1 b ja br 1 a. Jos R 1 olisi transitiivinen, niin silloin olisi ar 1 a, mikä ei kuitenkaan ole mahdollista. Siten R 1 ei ole transitiivinen. b) Relaatio R 2 ei ole reeksiivinen, symmetrinen eikä transitiivinen. Se on irreeksiivinen ja antisymmetrinen. c) Relaatio R 3 on reeksiivinen, symmetrinen ja transitiivinen. Se ei ole irreeksiivinen eikä antisymmetrinen. Esim. 12. Seuraavat relaatiot on määritelty kokonaislukujen Z joukossa. Luokittele relaatiot edellä edellä annettujen relaatio-ominaisuuksien nojalla. a) R 4 = { (a, b) a b } b) R 5 = { (a, b) a on jaollinen luvulla b } c) R 6 = { (a, b) a:lla ja b:llä on sama pariteetti } Ratkaisu. a) Relaatio R 4 on reeksiivinen, eikä ole irreeksiivinen (koska aina x x). Se ei ole symmetrinen: x y, mutta y x, jos x y. Jos x y ja y x, niin taatusti x = y, joten R 4 on antisymmetrinen. Jos x y ja y z, niin suuruusjärjestys säilyy ja x z, joten R 4 on transitiivinen. b) Relaatio R 5 on reeksiivinen ja transitiivinen, mutta ei ole symmetrinen eikä antisymmetrinen. Huomaa, että aina, kun x 0, on x R 4 ( x) ja ( x) R 4 x, mutta x ( x). c) Kokonaisluvuilla x ja y on sama pariteetti jos joko molemmat ovat parillisia tai molemmat ovat parittomia. Relaatio R 6 on reeksiivinen, symmetrinen ja transitiivinen. Se ei tietystikään ole irreeksiivinen eikä antisymmetrinen. Kahden edellisen esimerkin c-kohdissa esiintyvät relaatiot ovat reeksiivisiä, symmetrisiä ja transitiivisia. Relaatiotyypillä on oma nimi: ekvivalenssirelaatio. Siis Joukon A binaarirelaatio on A:n ekvivalenssi(relaatio), jos se on reeksiivinen, symmetrinen ja transitiivinen. Esimerkin 11 relaatio R 3 on ekvivalenssi. Se on reeksiivinen (' a:lla samat biologiset vanhemmat kuin a:lla'), symmetrinen ('jos a:lla on samat biologiset vanhemmat kuin b:llä, niin b:llä on samat biologiset vanhemmat kuin a:lla') ja transitiivinen ('jos a:lla on samat biologiset vanhemmat kuin b:llä ja b:llä on samat biologiset vanhemmat kuin c:llä, niin a:lla on samat biologiset vanhemmat kuin c:llä'). Ekvivalenssirelaatio kuvaa sitä, että tässä relaatiossa olevat alkiot ovat jollain 68

tapaa samanlaiset. Ekvivalenssirelaation avulla joukon alkiot voidaan jakaa pareittain erillisiin ekvivalenssiluokkiin. Jakaminen ei yleensä onnistu jollei kyseessä ole ekvivalenssirelaatio. Olkoon A epätyhjä joukko ja R joukon A ekvivalenssi. Jokaisella a A on joukko R(a) = {b b A arb} (alkiota a vastaava) R:n ekvivalenssiluokka. Koska ara, on a R(a), joten R(a) aina, kun a A. Olkoot a, b A sellaisia, että R(a) R(b). Olkoon c A sellainen alkio, että c R(a) ja c R(b). Tällöin arc ja brc. Koska R on symmetrinen, on crb. Koska arc ja crb ja R on transitiivinen, on arb. Nyt jokaisella d R(b) on brd jolloin saadaan ard eli c R(a) (jälleen R:n transitiivisuuden nojalla). Koska d R(b) oli mielivaltainen, on R(b) R(a). Vastaavalla tavalla osoitetaan, että R(a) R(b). Siispä R(a) = R(b). Osoitimme, että aina, kun a, b A, on voimassa joko R(a) R(b) = tai R(a) = R(b). Siten jokainen joukon A alkio kuuluu täsmälleen yhteen relaation R ekvivalenssiluokkaan. Joukon A ositukseksi sanotaan sellaista sen osajoukkojen kokoelmaa, että joukon A jokainen alkio kuuluu täsmälleen yhteen kokoelman osajoukoista. Edellä olevan päättelyn perusteella joukon A ekvivalenssirelaation ekvivalenssiluokat muodostavat aina joukon A osituksen. Esim. 13. Olkoon R sellainen kokonaislukujoukon Z relaatio, jolle xry, jos x y on jaollinen luvulla 4. Osoita, että R on Z:n ekvivalenssi ja määritä sen ekvivalenssiluokat. Ratkaisu. Olkoon x Z. Varmasti x x on jaollinen luvulla 4, joten xrx ja R on reeksiivinen. Olkoot x, y Z sellaisia, että xry. Tällöin x y on jaollinen luvulla 4. Epäilemättä myös (x y):n vastaluku y x on jaollinen 4:llä, joten yrx. Siispä R on symmetrinen. Olkoot nyt x, y, z Z sellaisia, että xry ja yrz. Tietysti x y ja y z ovat molemmat jaollisia 4:llä; olkoot m, n Z sellaisia, että x y = 4m jay z = 4n. Nyt x z = (x y) + (y z) = 4m + 4n = 4(m + n), joka on jaollinen luvulla 4. Siispä xrz. Olemme osoittaneet, että R on transitiivinen. Koska R on reeksiivinen, symmetrinen ja transitiivinen, se on ekvivalenssirelaatio. 69

Määritetään nyt R:n ekvivalenssiluokat. Tarkastellaan alkion 0 ekvivalenssiluokkaa: R(0) = { x x Z 0Rx } = { x x Z luku 4 jakaa luvun x } = {..., 12, 8, 4, 0, 4, 8, 12,...} Nyt 1 / R(0), joten tarkastellaan alkion 1 ekvivalenssiluokkaa: R(1) = { x x Z 1Rx } = { x x Z luku 4 jakaa luvun x 1 } = { x x Z n Z : x = 4n + 1 } = {..., 11, 7, 3, 1, 5, 9, 13,...} Luku 2 / R(0) R(1), joten tarkastellaan alkion 2 ekvivalenssiluokkaa: R(2) = { x x Z 2Rx } = { x x Z luku 4 jakaa luvun x 2 } = { x x Z n Z : x = 4n + 2 } = {..., 10, 6, 2, 2, 6, 10, 14,...} Luku 3 / R(0) R(1) R(2), joten tarkastellaan vielä alkion 3 ekvivalenssiluokkaa: R(3) = { x x Z 3Rx } = { x x Z luku 4 jakaa luvun x 3 } = { x x Z n Z : x = 4n + 3 } = {..., 9, 5, 1, 3, 7, 11, 15,...} Pitemmälle meidän ei tarvitse mennäkään ekvivalenssiluokkia tarkastellessamme; jokainen luku x Z kuuluu johonkin ekvivalenssiluokista R(0), R(1), R(2) tai R(3). Siispä {R(i)} i {0,1,2,3} on joukon Z ositus. Kun halutaan osoittaa, että jonkin ongelman tarkastelussa ilmi tullut relaatio on ekvivalenssi, täytyy tietysti osoittaa, että se on reeksiivinen, symmetrinen ja transitiivinen. Ensimmäinen tehtävä on selvittää, mitä reeksiivisyys, symmetrisyys ja transitiivisuus kyseisessä ongelmassa tulkitaan, mitä se pitää sisällään. Ominaisuuksien osoittaminen voi sen jälkeen olla helppoakin. Osittaiset järjestykset ovat ekvivalenssien rinnalla tärkeitä binaarirelaatioita. Joukon A binaarirelaatio on A:n osittainen järjestys, jos se on reeksiivinen, transitiivinen ja antisymmetrinen. 70

Esim. 14. Esimerkkejä osittaisista järjestyksistä. (i) Relaatio 'pienempi tai yhtäsuuri kuin' ( ) reaalilukujen R joukossa. (ii) Relaatio joukon A potenssijoukossa P(A). (iii) Relaatio '(luku p) on tasan jaollinen (luvulla q )' positiivisten luonnollisten lukujen N + joukossa. Jos joukossa on määritelty osittainen järjestys, voimme muodostaa hierarkian, jossa jotkut joukon alkioista ovat toisia 'suurempia' (tai vastaavasti 'pienempiä'). Sana 'osittainen' viittaa siihen, ettei alkioiden välillä välttämättä ole järjestystä; esim. (osa)joukkojen A ja B tapauksessa kumpikaan suhteista A B tai B A ei välttämättä ole voimassa. Toisaalta taas reaalilukujoukossa on ns. täysi järjestys: jokaisella x, y R on voimassa joko x y tai y x. Tarkastellaan Esimerkki 14:n kohtaa (iii) ja osoitetaan, että kysymys on osittaisesta järjestyksestä. Olkoot x ja y positiivisia kokonaislukuja. Tällöin y on tasan jaollinen x:llä jos on olemassa sellainen k N +, että y = k x. Olkoot nyt m, n, r positiivisia kokonaislukuja. On selvää, että m jakaa tasan itsensä, joten tasan jakaminen on reeksiivinen (joukossa N + ). Oletetaan sitten, että m jakaa tasan n:n ja n jakaa tasan m:n. Tällöin on voimassa m = k 1 n ja n = k 2 m joillakin k 1, k 2 N +. Saadaan n = k 1 m = (k 1 k 2 ) m, josta seuraa, että k 1 k 2 = 1. Siispä saadaan m = n, joten tasan jaollisuus on antisymmetrinen (N + :ssa). Oletetaan viimeiseksi, että m jakaa tasan n:n ja n jakaa tasan r:n. Tällöin määritelmän mukaan n = k 3 m ja r = k 4 n joillakin k 3, k 4 N +. Saadaan r = k 4 n = (k 4 k 3 ) m, josta seuraa, että r on tasan jaollinen m:llä. Siispä tasan jaollisuus on transitiivinen ( N + :ssa). Edellisen nojalla tasan jaollisuus on osittainen järjestys positiivisten kokonaislukujen joukossa; se ei ole (täysi) järjestys, esim. luku 3 ei jaa tasan lukua 5 eikä luku 5 jaa tasan lukua 3. Osittaisia järjestyksiä esiintyy tuon tuostakin laskennan eri aloilla. Oletetaan, että tietokoneohjelma on kokoonpantu moduleista: pääohjelmasta, aliohjelmista, joita pääohjelma kutsuu, aliohjelmista, joita pääohjelman kutsumat aliohjelmat kutsuvat, jne... Määritellään relaatio R tietokoneohjelman modulijoukossa {m 1, m 2,..., m n } seur. säännöllä: m i Rm j, jos m i on modulin m j kutsumisjonossa (eli joko m i on sama moduli kuin m j tai löytyy sellainen ketju kutsuja, että m j :stä päästään moduliin m i. Selvästi R on reeksiivinen ja transitiivinen. Mikäli R ei ole antisymmetrinen, sykliset (eli sirkulaariset) kutsut ovat mahdollisia. Ohjelmoinnissa rekursiivisuus on vahva itekniikka; tu- 71

tustumme siihen myöhemmin. Mikäli emme halua käyttää rekursiivisia kutsuja relaation R tulee olla osittainen järjestys. 4.6 Funktiot ja laskenta tietokoneella Lukiomatematiikassa tavatut funktiot ovat enimmäkseen 'reaalimuuttujan reaaliarvoisia kuvauksia', joista voidaan mukavasti muodostaa yhtälöitä ja konstruoida kuvaaja. Seuraavassa tarkastelemme funktiokäsitettä jonkin verran yleisemmästä näkökulmasta; näin siksi, että laskennassa käytetyt ja korkean tason ohjelmointikielten kirjastoissa esiintyvät funktiot edustavat sangen laajaa kuvausten skaalaa. Olkoot A ja B joukkoja. Funktio joukosta A joukkoon B on (mikä tahansa) sääntö, joka jokaiseen A:n alkioon liittää yksikäsitteisesti määrätyn B :n alkion. Funktioita merkitsemme pienillä kirjaimilla f, g, h,... mahdollisesti alaindeksillä varustettuna. Myös kreikkalaisia kirjaimia ( α, β, ρ, φ) käytetään usein funktion niminä. Jos f on funktio joukosta A joukkoon B, merkitsemme f : A B. Tällöin A on f :n määrittely- eli lähtöjoukko ja B sen maalijoukko eli tulojoukko. Merkitsemme f(x):llä sitä B :n alkiota, jonka f liittää A:n alkioon x. Sanomme, että f(x) on x:n kuva ja x puolestaan f(x):n alkukuva. Edelleen sanotaan, että f kuvaa (joukon A) alkion x (joukon B ) alkioksi f(x). Huomattakoon, että koulusta tuttu merkintä y = f(x) liittyy reaalimuuttujan reaaliarvoiseen funktioon ja sen kuvaajaan {(x, f(x)) x R }, joka voidaan piirtää xy -koordinatistoon. Esim. 15. Olkoon f : R R funktio, jolle f(x) = x 2. Funktion lähtöjoukko on R, samoin maalijoukko. Funktio kuvaa lähtöjoukkonsa alkiot ei-negatiivisiksi reaaliluvuiksi. Voimme ajatella funktiota f tässä 'neliöönkorotuskoneena', joka syötteellä x antaa tulosteen f(x). Miten syötettä merkitään, ei itse asiassa ole tärkeää. Merkitystä on sillä, miten f kuvauksen suorittaa, miten tuloste riippuu syötteestä. Funktion f : A B kuvajoukko on kaikkien sellaisten alkioiden y B joukko, että y = f(x) jollakin x A: { y x : x A y = f(x) } 72

Esim. 16. Olkoon A = {1, 2, 3} ja B = {1, 2, 3, 4}. Määritellään funktio f : A B seuraavasti: f(1) = 3, f(2) = 2 ja f(3) = 2. Tässä f :n määrittelyjoukko on tietysti {1, 2, 3}, maalijoukko {1, 2, 3, 4} ja kuvajoukko {2, 3}. Kuvaajan voi helpoiten esittää suunnattuna verkkona. Esim. 17. Olkoon C kaikkien ASCII-merkkien joukko. Kullakin ASCII-merkillä (engl. ASCII character) on yksikäsitteinen merkkikoodi (engl. character code) joukossa {0, 1, 2,..., 127}. Vastaavasti jokainen luku joukossa {0, 1, 2,..., 127} on täsmälleen yhden ASCII-merkin merkkikoodi. Määritellään funktiot seuraavasti: ord : C {0, 1, 2,..., 127} ja chr : {0, 1, 2,..., 127} C ord(c) = ASCII - merkin c merkkikoodi chr(n) = se ASCII - merkki, jonka merkkikoodi on n. Tässä ord:n määrittelyjoukko on tietysti C, maalijoukko {0, 1, 2,..., 127} ja kuvajoukko {0, 1, 2,..., 127}. Funktion chr määrittelyjoukko on puolestaan {0, 1, 2,..., 127} ja maalijoukko sekä kuvajoukko C. Funktio f : A B voidaan aina tulkita joukoksi { (a, f(a)) a A } ja siten joukkojen A ja B väliseksi relaatioksi. Siis jokainen funktio : A B määrittelee yksikäsitteisesti joukkojen A ja B välisen relaation. Kääntäen, jokainen sellainen relaatio R A B, että jokaista alkiota a A kohti on olemassa täsmälleen yksi sellainen alkio b B, että (a, b) R määrittelee yksikäsitteisesti funktion joukosta A joukkoon B. Esim. 18. Olkoon B = {0, 1} binaariaakkosto ja B + kaikkien epätyhjien äärellistä pituutta olevien bittijonojen muodostama joukko. 2 Määrittelevätkö seuraavat relaatiot funktion? Perustele vastauksesi. 2 Määritelmän mukaisesti B + = { b 1 b 2 b n n N+ ja b i B, kun i = 1, 2,..., n }. 73

a) R 1 B + N, R 1 = { (x, n) n on ykkösten lukum. jonossa x } b) R 2 B + N, R 2 = { (x, b) b on 1. bitti jonossa x } c) R 3 B + N, missä R 3 = { (x, n) bitti 0 esiintyy x:ssä paikassa n ensimmäistä kertaa} d) R 4 B + B +, R 4 = { (x, xb) x B + ja b B, } e) R 5 N B +, R 5 = { (n, 1 n ) n N+ }. Funktio f : A B on surjektio, jos sen kuvajoukko on sama kuin sen maalijoukko; toisin sanoen f(a) merk. = { f(a) a A } = B. Jos funktio on surjektio, niin jokaisella sen maalijoukon alkiolla on alkukuva. Funktio f : A B on injektio, jos se ei kuvaa lähtöjoukon kahta eri alkiota samalle maalijoukon alkiolle; loogisesti ilmaistuna x z [ x z f(x) f(z) ]. Funktio, joka on sekä surjektio että injektio on bijektio. Esim. 19. Päätä ovatko seuraavat funktiot surjektioita, injektioita tai bijektioita. a) f : R R, f(x) = 2x + 1 b) ord Esimerkissä 17 c) chr Esimerkissä 17 d) Esimerkin 18 a-kohdan funktio e) Esimerkin 18 b-kohdan funktio f) φ : B + B +, φ(s) = s0. Kun päätetään funktion surjektiivisuudesta, täytyy vastata kysymykseen: 'Onko jokaisella funktion maalijoukon alkiolla alkukuva? Jos on, funktio on surjektio. Jos ei ole, funktio ei ole surjektio. Kun päätetään funktion injektiivisyydestä, täytyy vastata kysymykseen: 'Onko olemassa sellaiset lähtöjoukon eri alkiot, jotka kuvautuvat kuvajoukon samalle alkiolle?' Jos eri alkiot löytyvät, funktio ei ole injektio. Mikäli tällaisia alkioita ei ole, funktio on injektio. Olennaisesti injektiivyys päätetään ratkaisemalla yhtälö f(x 1 ) = f(x 2 ) (mikä voi olla pahuksen vaikeaakin). 74

ei surjektio eikä injektio ei surjektio on injektio surjektio ei injektio on surjektio ja injektio ei funktio olleskaan Kuva 4.4: Funktioita 4.7 Yhdistetty funktio ja käänteisfunktio Olkoot f : A B ja g : B C funktioita. Jos miellämme ne syöte-tuloste -koneina, ajatella f :n tulosteen olevan g :n syöte Kuvan 4.5 mukaisesti. Edellä esitetyn yhdistämisprossin tuloksena saadaan yksi syöte-tuloste -kone, joka ottaa syötteenä alkion x ja tulostaa alkion g(f(x)). Tämä uusi kone vastaa f :n ja g :n yhdistettyä funktiota. Funktioiden f : A B ja g : B C yhdistetty funktio on funktio g f : A C, (g f)(x) = g(f(x)). Esim. 20. Olkoot f ja g funktioita joukosta R joukkoon R, joille f(x) = x 2 ja g(x) = 3x 1. Määritä yhdistetyt funktiot g f ja f g. Kaksi funktiota f : A B ja g : A B ovat samat eli yhtäsuuret, merk. f g, mikäli f(x) = g(x) aina, kun x A. Mitä voit sanoa edellisen esimerkin yhdistettyjen funktioiden yhtäsuuruudesta? 75

x f(x) g(f(x)) f g Kuva 4.5: Funktioiden yhdistäminen Aakkosto on mikä tahansa epätyhjä joukko abstrakteja symboleita. Olkoon A aakkosto. Aakkoston A sana mikä tahansa äärellinen jono A:n symboleja. Olkoon w aakkoston A sana; tällöin w voidaan esittää muodossa w = a 1 a 2 a m, missä m N ja a i A, kun i = 1, 2,..., n. Edellä n on sanan w pituus; merkitään w:n pituutta merkkijonolla w. Jos n = 0, on w tyhjä sana, jota merkitään symbolilla ɛ. Aina, kun a A, olkoon w a symbolin a esiintymiskertojen lukumäärä sanassa w. Jokaisella n N, olkoon A n aakkoston A kaikkien n:n pituisten sanojen joukko. Olkoon A aakkoston A kaikkien sanojen joukko ja A + = A \ {ɛ}. Esim. 21. Olkoon A aakkosto, a A, sekä f : A + N ja g : A + A + funktioita joille f(w) = w ja g(w) = wa. Voidaanko seuraavista pareista muodostaa yhdistetty funktio? a) f, f b) f, g c) g, f d) g, g. Tarkastellaan Esimerkin 17 funktioiden ord : C {0, 1, 2,..., 127}, jolle ja chr : {0, 1, 2,..., 127} C, jolle ord(c) = merkin c ASCII-koodi chr(n) = koodia n vastaava ASCII-merkki 76

yhdistettyjä funktioita chr ord : C C ja ord chr : {0, 1, 2,..., 127} {0, 1, 2,..., 127}. Havaitsemme, että (chr ord)(c) = c aina, kun c C ja (ord chr)(n) = n aina, kun n {0, 1, 2,..., 127}. Informaatiota ei siis funktioita yhdistettäessä katoa. Johdumme käänteisfunktion käsitteeseen. Tarvisemme vielä yhden määritelmän. Olkoon A joukko ja id A : A A funktio, jolle id A (a) = a. Tällöin id A joukon A identiteettifunktio. on Funktio id A ei oikeastaan tee mitään; se kuvaa jokaisen lähtöjoukon alkion alkiolle itselleen. Jos g on funktio, jonka lähtöjoukko on A ja h funktio, jonka maalijoukko on A, on selvästikin voimassa g id A = g ja id A h = h. Olkoot f : A B ja g : B A funktioita, joille g f = id A ja f g = id B. Tällöin g on f :n käänteisfunktio (ja kääntäen: f on g :n käänteisfunktio). Voimme ajatella, että funktion f : A B käänteisfunktio (silloin, kun se on olemassa) on kone, joka muuttaa päivastaiseksi f :n toiminnan; kun kuljetin f vie joukon A alkion a joukon B alkioksi f(a), 'käänteiskuljetin' f 1 vie f(a):n takaisin a:ksi. Esim. 22. Olkoon f : {a, b, c} {1, 2, 3} funktio, jolle f(a) = 2, f(b) = 3 ja f(c) = 1. Määritä f 1. Jotta käänteisfunktio voisi olla olemassa, mitkään kaksi eri alkiota eivät voi kuvautua samalle alkiolle. Muutenhan ei voitaisi päättää miten mainittu kuvaalkio kuvautuisi käänteisfunktiossa. Jos funktiolla on käänteiskuvaus, se on siten väistämättä injektio. Koska käänteiskuvauksen on kuvattava jokainen alkio jotenkin, funktion on myös oltava surjektio, jotta sillä voisi olla käänteisfunktio. Näin ollen vain bijektiolla voi olla käänteisfunktio. Edelleen bijektiolla on aina välttämättä käänteisfunktio, koska se antaa yksikäsitteisen vastaavuuden lähtöjoukon ja maalijoukon akioiden välille. Siksi on voimassa Lause 2. Funktiolla f on käänteisfunktio jos ja vain jos f on bijektio. Esim. 23. Onko seuraavilla funktioilla käänteisfunktiot? (a) f : R R, f(x) = 2x + 1 (b) g : R R, g(x) = x 2 (c) h : R R, g(x) = x 2, missä R on kaikkien ei-negatiivisten reaalilukujen muodostama joukko. Minkälaisissa käytännön tilanteissa käänteisfunktioita tarvitaan? Seuraavassa pari esimerkkiä. 77

Internetin yli kommunikoitaessa on tärkeää salata viestit, jotka sisältävät luottamuksellista tietoa. Näin siksi, että emme halua verkossa mahdollisesti vaanivan urkkijan saava tietoa yksityisistä asioistamme. Tietysti vastaanottajan on kyettävä palauttamaan alkuperäinen viesti. Olkoon M selkokielisten viestien joukko, C salattujen viestien joukko ja f : M C salausfunktio. On selvää, että jokainen viesti m M on pystyttävä salaamaan ja tietysti yhdeksi ainoaksi kryptoviestiksi, joten f on funktio (minkä jo oletimmmekin). Niinikään kahta eri selkokielistä viestiä ei tule salata samaksi kryptoviestiksi; avaamisvaiheessa on tuloksena oltava yksikäsitteinen selkokielinen viesti. Siten f :n tulee olla injektio. Jotta kyetään takamaan se, että jokainen kryptoviesti voidaan avata, tulee f :n olla surjektio. Täten salaajan on oltava bijektio; käänteisfunktio f 1 on siten olemassa ja on se avausfunktio. Vastaavanlainen tilanne kuin salauksessa tapahtuu tiedostoja pakkausohjelmia käytettäessä. Pakkaamisprosessi, jonka tuloksena saatu tiedosto vaatii vähemmän tilaa kuin alkuperäinen, muistuttaa salaamista; tarkoitus on luoda merkkijono, joka yksikäsitteisesti voidaan palauttaa alkuperäiseksi tiedostoksi. Oletetaan, että pakkaaminen suoritetaan toiminnolla g eikä pakattava tiedosto voi olla pitempi kuin d bittiä. Oletetaan edelleen, että jokainen korkeintaan d bittiä sisältävä jono on kyettävä pakkaamaan. Siten pakattavien tiedostojen joukko on A = {w {0, 1} + w d}. Olkoonpa nyt B kaikkien pakattujen tiedostojen joukko. Tällöin g on funktio joukosta A joukkoon B ; näin siksi, että ei ole järkevää, jos pakkauksen tuloksena yhdestä tiedostosta saadaan useampia pakkausvaihtoehtoja. Edelleen, jokasta pakattua tiedostoa kohti tulee olla yksikäsitteinen alkuperäinen tiedosto (pakkauksen purkamisen täytyy olla yksikäsitteinen toiminto). Siispä g :n on oltava injektio. Surjektio g on koska jokainen pakattu tiedosto on kyettävä purkamaan alkuperäiseksi. Tietysti olisi toivottava, että jokainen tiedosto lyhenisi (aidosti) pakkaamisprosessissa. Onko tämä mahdollista? Ei ole. Oletetaanpa, että jokainen pienenee aidosti kooltaan pakattaessa. Tällöin B on joukon A aito osajoukko. Siispä (laatikkoperiaatteen nojalla) voitaidaan löytää kaksi eri A:n alkiota, jotka kuvautuvat samalle B :n alkiolle. Eli meillä on A palloa, jotka asetetaan ( g :tä käyttäen) B laatikkoon. Koska palloja on enemmän kuin laatikoita, joutuvat jotkin kaksi palloa samaan laatikkoon. Siten g ei ole injektio. Edellä totesimme,että injektiivisyys on pakkauksen välttämätön ominaisuus, joten B ei voi olla A:n aito osajoukko. Kaikki tiedostot eivät siten voi pakattaessa kooltaan aidosti pienentyä. Olemme todistaneet seuraavan tuloksen: Ei ole olemassa pakkausalgoritmia, joka pienentää aidosti kaikkien tiedostojen kokoa. Tarkemmin päättelyketjuamme tarkasteltaessa havaitaan, että vahvempikin tulos on voimassa: Pakkausal- 78

goritmin aidosti pienentämien tiedostojen lukumäärä on korkeintaan yhtäsuuri kuin sen aidosti suurentamien tiedostojen lukumäärä. Tiedostojen pakkaus on nykyaikana jokapäiväistä toimintaa. Pakkaamiseen tarkoitetut algoritmit ovat tehokkaita ja kykenevät pienentämään useimpien käytännössä esiintyvien tiedostjen kokoa. Kannattaa kuitenkin muistaa, että jokaiselle pakkausmenetelmälle löytyy tiedostoja, joiden kokoa se ei kykene pienentämään. 4.8 Funktiot ohjelmointikielissä Useimmat ohjelmointikielet (myös taulukkolaskentaaan ja tietokantojen käsittelyyn tarkoitetut) sisältävät konstruktioita, joita kutsutaan 'funktioiksi'. Useimmissa kielissä on laajat funktiokirjastot; ohjelmoijat voivat tietysti luoda myös omia funktioitaan. Taulukkolaskentasoftassa funktio ABS tavallisesti ottaa syötteenä reaaliluvun x ja palauttaa sen itseisarvon x. Vomme siten ajatella, että ABS on funktio joukosta R joukkoon R. Tässä R kyllä tarkasti ottaen tarkoittaa reaalilukujen tietokone-esityksiä. Toinen esimerkki taulukkolaskentaan liittyvistä funktioista on kuvaus, joka ratkaisee, onko taulukkosolun sisältö tekstimerkkijono (text string). Funktio voisi olla nimeltään ISTEXT, joka voisi syötteenä ottaa monentyyppistä dataa: kirjainmerkeistä, luvuista tai loogisista ehdoista koostuvia jonoja tai (kuten usein tapahtuu): taulukossa esiintyvän solun osoitteen. Tuloste olisi TRUE, jos syöte (tai osoitetta vastaavan solun sisältö) on tekstimerkkijono ja FALSE, jos se ei sitä ole. Jos X merkitsee kaikkien oikeantyyppisten datayksiköiden ja soluosoitteiden joukkoa, on ISTEXT : X {TRUE, FALSE} funktio. Kolmas esimerkkimme koskee funktiota LEFT, jolla on kaksi argumenttia: aakkosmerkkijonosta koostuva argumentti s ja luonnollinen luku n; syötteellä (s, n) funktio LEFT palauttaa s:n n ensimmäistä symbolia. Jos S on kaikista aakkosmerkkijonojen joukko, on LEFT funktio joukosta S N joukkoon N. Mikä tahansa vakio (tietokoneissa esim π ja Neperin luku e) voidaan käsittää triviaaliksi funktioksi. Ohjelmointikielet (esim. Pascal ja C) sisältävät, paitsi funktiokirjastoja, myös mahdollisuuden luoda omia funktioita. Tyypillinen Pascalin funktio-otsake voisi olla esimerkiksi: 79

function f(x: char; y: real): integer. C-kielessä vastaava otsake näyttää seuraavalta: int f(char x, float y) Kun funktio määritellään, funktion runko seuraa otsaketta; se sisältää algoritmin, joka laskee f :n arvon argumentin arvoilla x ja y. Matematiikan kannalta f :n lähtöjoukko on C R:n osajoukko; tässä C on koneessa saatavilla olevien merkkien joukko, maalijoukko puolestaan on N:n osajoukko. Monissa ohjelmointikielissä 'funktion' palauttama arvo riippuu muistakin kuin ohjelmoijan käytettävissä olevista argumenteista. Tällaisia voivat olla esim. tietyt globaalit muuttujat, jotka edustavat ohjelman suorituksen (tai tietokoneen) sisäistä tilaa. Tällöin samalla ohjelman käyttäjän antamalla syötteellä voidaan saada eri tulosteita. Lisäksi, esimerkiksi C-kielessä, monet funktiot eivät palauta mitään (käyttäjälle) näkyvää arvoa. Tämän vuoksi ohjelmointikielen 'funktio' ei varsinkaan yleisimmin käytetyissä, ns. imperatiivisissa kielissä käyttäjän näkökulmasta ole matemaattinen funktio. Sen sijaan ns. funktionaalisten kielten funktiot pyrkivät muistuttamaan matemaattisia funktioita mahdollisimman pitkälle. Esimerkkinä edellisestä tilanteesta tarkastellaan seuraavaa pseudosatunaislukugeneraattoria random, joka syötteellä (a, b), missä a, b R, a < b, palauttaa jonkin 'satunnaisluvun' väliltä (a, b). Mikäli tätä toimintoa kutsutaan esim. syötteellä (0, 1) useammin kuin kerran saadaan todennäköisesti eri vastauksia. Käyttäjän kannalta random ei ole matemaattinen funktio (ja hyvä on, ettei ole, kun ajatellaan sen käyttöä esim. tietoturvasovelluksissa). Täytyy kuitenkin huomata, että loppujen lopuksi, jos kaikki generointiin vaikuttavat argumenttien arvot otetaan huomioon, toimivat niin random kuin muutkin pseudosatunnaislukugeneraattorit täysin deterministisesti, joten tässä mielessä ne ovat funktioita. 80

5 Rekursio ja induktio Rekursio on yksinkertainen, mutta erittäin tehokas tapa konstruoida algoritmeja vaikeiden ongelmien ratkaisemiseksi. Tarkastelemme myös induktiotodistusta; induktio ja rekursio ovat saman asian kaksi eri puolta. Rekursiossa näkökulma on 'yleisestä yksityiseen' (tai ylhäältä alaspäin), induktiossa puolestaan yksityisestä yleiseen (alhaalta ylöspäin). Rekursio on tekniikka konstruoida algoritmeja, induktiota voidaan soveltaa mm. algoritmien oikeellisuuden todistamieen. 5.1 Rekursio ja jonot Näppärä tapa aloittaa rekursioon tutustuminen on tarkastella äärettömiä lukujonoja. Mikä tahansa reaalilukujono voidaan esittää muodossa a 1, a 2, a 3,... missä siis a n R aina, kun n N +. Tässä kolme pistettä ilmentää tilannetta, että lukujono jatkuu äärettömiin. Yo lukujono koostuu luvuista a 1, a 2, a 3,... ja kukin luku a n on jonon jäsen tai termi. Toinen tapa kirjoittaa edellinen lukujono on (a n ) n=1. Tarkastellaan parillisten positiivisten kokonaislukujen joukkoa 2, 4, 6, 8,.... Edellä a 1 = 2, a 2 = 4, a 3 = 6, a 4 = 8 jne... Jokainen lukujono (a n ) n=1 voidaan mieltää funktioksi positiivisten kokonaislukujen joukosta N + reaalilukujen joukkoon joukkoon R; tällöin luku n N + kuvautuu luvuksi a n. Parillisten positiivisten kokonaislukujen jono voidaan funktiomuodossa kirjoittaa t : N + R, t(n) = 2n ja sen yleinen termi saadaan yhtälöstä a n = 2n. Ymmärrämme siis lukujonon funktioksi, jonka lähtöjoukko on N + ja maalijoukko R. Alla esimerkkejä 81

lukujonoista ja niiden yleisistä termeistä. 3, 5, 7, 9, 11,... a n = 2n + 1 0.2, 0.9, 1.6, 2.3, 3.0,... a n = 0.7n 0.5 1, 4, 9, 16, 25, 36... a n = { n 2 0 jos n pariton 0, 1, 0, 1, 0, 1,... a n = 1 jos n parillinen Kun jonon yleinen termi annetaan, kyse on epärekursiivisesta esitystavasta. Epärekursiivinen määritelmä voi mukavasti toimia pohjana algoritmille. Mitä tekee seuraava algoritmi? Input: Positiivinen kokonaisluku m Output:? LUVUT(m) 1. for n=1 to m do 2. t = 2*n 3. print t Eipä ole yllä esitetty ainoa tapa, jolla jono 2, 4, 6, 8,... voidaan generoida; seuraavassa aasinsilta rekursiivisuuden tarkasteluun. Input: Positiivinen kokonaisluku m Output: m ensimmäistä parillista positiivista kokonaislukua PARILLISET(m) 1. t=2 2. for n=1 to m do 3. print t 4. t = t+2 Edellinen algoritmi perustuu jonon 2, 4, 6, 8,... uudentyyppiseen kuvaamiseen. Siinä on jonon aluksi annettu jonon ensimmäinen termi 2; tämän jälkeen jokainen seuraava termi saadaan edellisestä siihen luku 2 lisäämällä. Siis tarkemmalla matemaattisella notaatiolla: a 1 = 2 a n+1 = a n + 2 (n N + ) Täsä on annettu jonon 2, 4, 6, 8,... rekursiivinen määritelmä. Toisesta näkökulmasta katsottuna kyseessä on rekursioyhtälö. Yllä a 1 = 2 muodostaa määritelmän perustan ja a n+1 = a n + 2 sen rekursio-osan. On tärkeää ymmärtää, että jonon rekursiivinen ja (suljettu) epärekursiivinen määrittely ovat vain kaksi eri tapaa esittää sama asia eli kyseinen jono. 82

Esim. 1. Määrittele seuraava jono rekursiivisesti ja epärekursiivisesti. 2, 5, 8, 11, 14,... Ratkaisu. Tämäntyyppisen tehtävän voi ratkaista vain, jos jonon termit muodostuvat selkeän säännön mukaisesti. Lisäksi ratkaisijoilla tulee olla konsensus tästä säännöstä. Onko meillä? Olemmeko yhtä mieltä siitä, että jono alkaa luvulla 2 ja sen jälkeen termi kasvaa aina 3:lla edellisestä, toisin sanoen edetään 3:n suuruisissa askelisssa hamaan tulevaisuuteen. Ilmeisesti olemme. Tällöin saamme rekursiiviseksi määritelmäksi: Epäilemättä aina, kun n N + : a 1 = 2 a n+1 = a n + 3 (n N + ) a 1 = 2 a 2 = 2 + 3 a 3 = 2 + 3 + 3 a 4 = 2 + 3 + 3 + 3 = a n+1 = 2 + } 3 + 3 {{ + 3 } n kertaa = 3n + 2 Edellä rekursiivisen määritelmän löytäminen on aina hiukan ad hoc-puuhaa. Samaten epärekursiivisen suljetun muodon löytäminen voi olla hankalaa (jos rekursioyhtälö on monimutkainen). Lisäksi täytyisi kyetä todistamaan, että epärekursiivinen määritelmä vastaa rekursiivista. Jälkimmäisen voi tehdä induktiotodistusta käyttäen. Palaamme asiaan myöhemmin. Esim. 2. Määritä a 2, a 3 ja a 4 seuraavasta rekursiivisesti määritellystä jonosta. a 1 = 3 a n+1 = 2 a n + n + 1 (n N + ) Esim. 3. Kirjoita algoritmi, joka syötteellä m tulostaa Esimerkissä 2 määritellystä jonosta m ensimmäistä termiä. On huomattava, että vaikka edellisen esimerkin algoritmi implementoi rekursiivisesti määritellyn jonon, algoritmi itsessään ei ole rekursiivinen, koska algoritmi ei kutsu itseään. Algoritmi onkin iteratiivinen. 83

Aikaisemmissa esimerkeissä rekursiivisesti määritellyn jonon termi palautetaan sitä välittömästi edeltävään jonon termiin. Tämä on ehkä käytännössä yleisin tilanne, mutta aina näin ei tarvitse olla. Termi voi palautua useampaankin sitä jonossa edeltävään alkioon. Jos palautuskaavassa aikaisempien termien kertoimet ovat (rationaaliluku)vakioita, on kyse lineaarisesta rekursiosta. Esim. Fibonacci-jonossa 1 termi on aina kahden välittömän edeltäjänsä summa. f 1 = 1, f 2 = 1 f n+2 = f n+1 + f n (n N + ) Muutamien ensimmäisten termien mukaan Fibonacci-jono on: 1, 1, 2, 3, 5, 8, 13, 21,... Fibonacci-jonon epärekursiivinen suljettu muoto (eli Fibonacci-rekursioyhtälön ratkaisu) ei ole aivan yksinkertainen. Rekursiota käyttämällä voidaan näppärästi määritellä funktioita. Alla esimerkkinä kertoma. 0! = 1 (n + 1)! = n! (n + 1) (n N) Selvästi n! = n (n 1)(n 2) 2 1 aina, kun n N +. Sanomme tällöin, että n! on luvun n kertoma. Seuraavassa on annettu iteratiivinen algoritmi kertoman laskemiseksi. Input: Luonnollinen luku n Output: Luvun n kertoma KERTOMA(n) 1. f=1 2. for i=1 to n do 3. f = i*f 4. return f Rekursiivinen määritelmä voi koskea muutakin kuin lukujonoja; tarkastellaan kaarisulkeista '(' ja ')' konstruoitujen hyvin muodostettujen ilmaisujen määritelmää. 1. () on hyvin muodostettu ilmaisu; 2. jos w on hyvin muodostettu ilmaisu, niin (w), ()w ja w() ovat hyvin muodostettuja ilmaisuja. 1 'Fibonacci' oli Leonardo de Pisan (11751250) lempinimi 84

Edelleen propositiokalkyylin loogisen ilmaisun rekursiivinen määritelmä. 1. jokainen propositiomuuttuja on looginen ilmaisu; 2. jos P ja Q ovat loogisia ilmaisuja, niin P, P Q, P Q, P Q ja P Q ovat loogisia ilmaisuja. 5.2 Todistaminen induktiolla Alunperin induktiota käytettiin, kun haluttiin todistaa luonnollisia lukuja koskevia väitteitä. Sitä pystytään soveltamaan laajemminkin, kuten kohta tulemme näkemään. Paitsi että induktio on vahva matemaattinen tekniikka, se on tärkeä laskentasovelluksissa. Induktioon päädytään, kun katsotaan rekursiota toisesta suunnasta ja sitä voidaan soveltaa esim. tietokoneohjelmien ominaisuuksien todistamisessa. Kun halutaan todistaa väite induktiolla, se esitetään muodossa, jossa jokin ominaisuus on tosi kaikilla luonnollisilla luvuilla jostakin (perus)luvusta alkaen. Tällöin väite esitetään muodossa ' np (n)' missä n on mikä tahansa (ainakin perusluvun suuruinen) luonnollinen luku. Seuraavassa esimerkki: 1 + 2 + 3 + + n = n(n + 1) 2 aina, kun n N + Merkinnän 1 + 2 + + n sijasta voimme käyttää merkintää Σ n i=1i. Tässä Σ tarkoittaa summaamista ja i on indeksimuuttuja, joka saa edellä arvot 1:stä n:ään. Lauseketta voidaan käyttää määrittelemään monimutkaisempiakin summalausekkeita, esimerkiksi jos f on jokin funktio ja haluttaisiin kirjoittaa merkinnällä summalauseke f(1) + f(2) + + f(n) niin se olisi Σ n i=1f(i). Palataan alkuperäiseen väitteeseen. Jotta väite tulisi todistetuksi, meidän täytyy kyetä osoittamaan, että se pitää paikkansa jokaisella arvolla n N +. Näitä arvoja on ääretön määrä, joten emme pysty osoittamaan väitettä oikeaksi laskemalla summan yksitellen eri n:n arvoilla. Täytyy löytää yleisempi tapa: induktiotodistus on sellainen. Olkoon P jokin luonnollista lukua n koskeva väite ja n 0 N. Väitteen 'P (n) on tosi aina, kun n N ja n n 0 ' todistaminen induktiolla tapahtuu askelittain seuraavasti. 85

1. Perusaskeleessa osoitetaan, että P (n) on tosi, kun n = n 0 eli, että P (n 0 ) on tosi. 2. Induktio-oletus sanoo, että P (n) on tosi yleisellä kiinteällä n:n arvolla n = k, eli, että P (k) on tosi, kun k N ja k n 0. 3. Induktioväite esittää, että P (k + 1) on tosi. 4. Induktiotodistuksessa puolestaan osoitetaan induktio-oletukseen nojautuen, että P (n) on tosi, kun n = k + 1, eli että P (k + 1) on tosi. Mikäli yllä esitetyt askeleet kyetään suorittamaan, teemme johtopäätöksen, että P (n) on tosi kaikilla sellaisilla luonnolisen luvun n arvoilla, että n n 0. Järkeily sujuu seuraavasti. P (n) on tosi, kun n = n 0, koska perusaskel on osoitettu oikeaksi. Koska P (n 0 ) on tosi, saadaan askelten 2, 3 ja 4 nojalla, että P (n 0 + 1) on tosi. Koska P (n 0 + 1) on tosi, saadaan (edelleen askelten 2, 3 ja 4 nojalla), että P (n 0 + 2) on tosi, jne... Olipa nyt n n 0 mikä tahansa luonnollinen luku, voimme etenemällä sopivan monta askelta edellämainittua päättelyketjua etenemällä osoittaa, että P (n) tosi. Siispä P (n) on tosi aina, kun n N, n n 0. Siis muodollisemmin n N : n n 0 P (n). Induktiotodistus etenee kuin kaatuva dominopalikkajono; kun 1. palikka kaatuu (eli voidaan osoittaa, että P (n 0 ) tosi), katuu myös toinen palikka (koska kykenemme osoittamaan, että jos P (k) on tosi, niin P (k + 1) on tosi), sen jälkeen kolmas, jne... Esim. 4. Osoita induktiolla, että aina, kun n N +. 1 + 2 + + n = n(n + 1) 2 (5.1) Ratkaisu. Nyt P (n) on väite 1 + 2 + + n = n(n+1) 2 ja n 0 = 1. Perusaskel. Osoitetaan, että P (1) on tosi. Asia on selvä, koska 1 = 1(1+1) 2. Induktio-oletus. Olkoon k N +. Oletetaan, että P (k) on tosi eli 1 + 2 + + k = k(k + 1) 2 Induktioväite. Väitetään, että (jos induktio-oletus on voimassa). 1 + 2 + + (k + 1) = (k + 1)(k + 2) 2. 86

Induktiotodistus. Tehdään päättelyketju: 1 + 2 + + (k + 1) = (1 + 2 + + k) + (k + 1) = k(k+1) 2 + (k + 1) (induktio-oletus) = k2 +k+2(k+1) 2 = k2 +3k+2 2 = (k+1)(k+2) 2. Siispä induktioväite P (k + 1) on tosi ja induktiotodistus loppuun suoritettu. Siten n(n + 1) 1 + 2 + + n = 2 aina, kun n N +. Huomattakoon, että emme millään tavalla johtaneet kaavaa (5.1). Sen oikeellisuus toki voidaan loogisesti perustella, mutta periaatteessa myös sivistyneesti arvata. Arvauksen jälkeen todistaminen voidaan suorittaa induktiolla. Tämä on induktion luonne: itsessään sen avulla ei juuri pysty uusia tuloksia johtamaan, mutta sen sijaan sen avulla voi osoittaa todeksi muilla keinoin saadun totta olevan väittämän. Edellä esitetyn Esimerkin 4 todistus on aika pitkä; askelten yksityiskohtia ei käytännössä aina tarvitse kirjoittaa ylös. Ei liioin väitteen tarvitse joka kerta koskea kaavaa tai yhtälöä. Esim. 5. Osoita, että n 2 + n on parillinen luku aina, kun n N +. Ratkaisu. Perusaskel. Kun n = 1, on n 2 + n = 1 2 + 1 = 2, joka on parillinen. Induktioaskel. Olkoon k N +. Oletetaan, että k 2 + k on parillinen. Tällöin (k + 1) 2 + (k + 1) = k 2 + 2k + 1 + k + 1 = (k 2 + k) + 2(k + 1). Luku k 2 + k on induktio-oletuksen nojalla parillinen. Koska myös 2(k + 1) on parillinen, on (k+1) 2 +(k+1) kahden parillisen luvun summana parillinen. Todistusten konstruoiminen induktiolla vaatii harjoittelua. Todistusten yksityiskohdat voivat poiketa toisistaan paljonkin, kun siirrytään ongelmasta toiseen. Yhteisiäkin piirteitä löytyy; ne kannattaa muistaa, koska ne ovat voimassa kaikissa induktiotodistuksissa. Seuraavassa yleisiä totuuksia induktiotodistuksesta. 1. Jokaisessa induktiotodistuksessa on perusaskel ja induktioaskel. 2. Perusaskel on tavallisesti helppo konstruoida. Joskus se vaikuttaa jopa triviaalilta, mutta se on olennainen osa induktiotodistusta ja täytyy aina todistukseen sisällyttää. 87

3. Induktioaskel alkaa induktio-oletuksella. Kirjoitetaan 'Oletetaan, että', jota seuraa todistettavana oleva väite, jossa n on korvattu k :lla. 4. Induktioaskel jatkuu osoittamalla, että todistettava väite on tosi, kun n korvataan (k + 1):llä. Induktio-oletusta tulee käyttää jossakin päättelyn vaiheessa. 5. Todistus päättyy toteamukseen, että alkuperäinen väite on tosi kaikilla halutuilla n:n arvoilla. 5.3 Induktion yhteys rekursioon Kuten aikaisemmin jo mainittiin, induktio ja rekursio ovat saman asian kaksi eri puolta. Rekursiivinen määritelmä koostuu perusosasta (usein n = 0 tai n = 1, mutta voi periaatteessa olla n = n 0, missä n 0 on mikä mikä tahansa luonnollinen tai jopa kokonaisluku. Sen jälkeen annetaan rekursiokaava, sääntö, jolla yleinen tapaus palautetaan edellisiin. Vastaavalla tavalla induktiotodistuksessa ensin osoitetaan tapaus n = n 0 ja sen jälkeen yleinen tapaus (induktioväite) todistetaan edellisten tapausten (jotka induktio-oletus takaa oikeiksi) avulla. Käytetään seuraavassa rekursion ja induktion yhteyttä siten, että rekursiivisen ajattelun intuitiivisesti tuottama väite todistetaan oikeaksi induktiolla. Esim. 6. Määritellään jono rekursiivisesti seuraavasti. a 1 = 1 a n+1 = a n + 2n + 1 (n N + ) Minkä (epärekursiivisen) yhtälön a n toteuttaa? Todista väitteesi induktiolla. Olemme aikaisemmin nähneet, että algoritmeja voidaan käyttää sekä rekursiivisesti että epärekursiivisesti määriteltyjen jonojen alkioiden generoimiseen. Joskus on tarpeen osoittaa, että rekursiiviseen määritelmään perustuva algoritmi todella tuottaa haluamammme lopputuloksen. Esim. 7. Osoita, että seuraava algoritmi syötteellä n N + tulostaa n:n ensimmäisen positiivisen kokonaisluvun kolmannet potenssit (kuutiot). 88

Input: Positiivinen kokonaisluku n Output: n:n ensimmäisen positiivisen kokonaisluvun kuutiot KUUTIOT(n) 1. ikuutio=0 2. for i=1 to n do 3. j = 3*i*(i-1)+1 4. ikuutio = ikuutio+j 5. print i,ikuutio Ja nyt varoituksen sana. Yleisesti ottaen annetun tietokoneohjelman toiminnan oikeaksi todistaminen on äärimmäisen vaikeaa, se on itse asiassa todistettu algoritmisesti ratkemattomaksi ongelmaksi (siis tietokoneella ei voi todistaa mielivaltaisen tietokoneohjelman toimivan oikein). Yllä tarkastelemme ongelmaa hyvin rajatussa ympäristössä, erittäin rajoitetuille algoritmityypeille. Sellaisiin kysymyksiin, onko algoritmi oikein implementoitu tietyllä ohjelmointikielellä tai aiheuttaako datan varastointi tai käsittely tietokoneessa joitakin ongelmia, emme ole puuttuneet ollenkaan. 5.4 Lineaarinen rekursioyhtälö Edellä nähtiin, että rekursiivisesti annetun lukujonon yleisen termin (epärekursiivinen) esitystapa voidaan todistaa oikeaksi induktiolla. Lueteltuamme jonon muutaman ensimmäisen jäsenen, arvasimme ksusti yleisen termin ja osoitimme, että osuimme oikeaan. Nytpä herää kysymys, onko olemassa systemmattista tapaa löytää rekursiivisesti annetun lukujonon yleisen termin kaava. Vastaus tähän kysymykseen riippuu rekursiivisen määritelmän rakenteesta. Osoitamme seuraavassa, että jos lukujono on annettu 1. tai 2. asteen (homogeenisena) lineaarisena vakiokertoimisena rekursioyhtälönä, voidaan suljettu muoto löytää homogeenisessa tapauksessa aina ja epähomogeenisessa tapauksessakin kohtalaiselle joukolle tietyntyyppisiä funktioita, jotka yhtälöstä epähomogeenisen tekevät. Tarkastellaan rekursioyhtälöä a n+1 = c a n (n N + ) (5.2) missä c 0 on reaalilukuvakio. Selvästi (5.2) määrittää geometrisen jonon, jonka suhdeluku on c. Induktiolla n:n suhteen nähdään helposti, että 89

a n = a 1 c n 1 (n N + ) (5.3) Yhtälö (5.2) on 1. asteen homogeeninen lineaarinen vakiokertoiminen rekursioyhtälö ja (5.3) on sen yleinen ratkaisu. Yleisen ratkaisusta tekee se, että emme ole kiinnittäneet yhdenkään termin lukuarvoa. Termin a 1 (tai jonon minkä muun tahansa jäsenen) arvo voidaan kiinnittää etukäteen ns. alkuehdolla. Esim. 8. Ratkaise rekursioyhtälö a n+1 = 7 a n, (n N + ), kun alkuehto on a) a 1 = 3 b) a 3 = 98. Esim. 9. Pankki maksaa talletukselle 3 prosentin vuotuista korkoa, ja korko lisätään pääomaan kuukausittain. Turo tallettaa 4000 euroa joulukuun 1. päivänä 2010. Mikä on talletuksen määrä vuotta myöhemmin, kun välillä ei ole ottoja eikä talletuksia? Olkoot nyt c 1 ja c 2 reaalilukuvakioita, c 2 0. Tällöin a n+2 = c 1 a n+1 + c 2 a n (n N + ) (5.4) on 2. asteen homogeeninen lineaarinen vakiokertoiminen rekursioyhtälö. Ratkaisun (5.3) inspiroimana tutkailkaamme sitä, mitä tapahtuu, jos t(n) = r n, n N + olisi (5.4):n ratkaisu jollakin nollasta poikkeavalla reaaliluvualla r. Saamme r n+2 c 1 r n+1 c 2 r n = 0 (n N + ) Ottamalla edellä yhtälön vasemmalla puolella yhteinen tekijä r n eteen, huomaamme, että r n (r 2 c 1 r + c 2 ) = 0 (n N + ). Koska r 0, luvun r täytyy toteuttaa yhtälö r 2 c 1 r c 2 = 0, (5.5) jota kutsutaan rekursioyhtälön (5.4) karakteristiseksi yhtälöksi. Seuraava tulos valottaa sitä, miten karakteristinen yhtälö liittyy rekursioyhtälön (5.4) ratkaisemiseen. Lause 1. Olkoot rekursioyhtälön (5.4) karakteristisen yhtälön (5.5) juuret reaalilukuja r 1 ja r 2. a) Jos r 1 r 2, on a n = A r n 1 + B r n 2, (n N +) rekursioyhtälön (5.4) ratkaisu jokaisella A:n ja B :n reaalilukuarvolla. Edelleen, jos (b n ) n=1 on reaalilukujono, joka toteuttaa rekursioyhtälön (5.4), voidaan löytää sellaiset reaaliluvut 90

A 0 ja B 0, että b n = A 0 r n 1 + B 0 r n 2, (n N +). b) Jos r 1 = r 2, on a n = (A n + B)r n 1, (n N +) rekursioyhtälön (5.4) ratkaisu on reaaliluku- jokaisella A:n ja B :n reaalilukuarvolla. Edelleen, jos (b n ) n=1 jono, joka toteuttaa rekursioyhtälön (5.4), voidaan löytää sellaiset reaaliluvut A 0 ja B 0, että b n = (A 0 n + B 0 )r1 n, (n N +). Olkoot r 1 ja r 2 karakteristisen yhtälön (5.5) juuret. Hyvällä syyllä voimme nyt sanoa, että jos r 1 r 2 [vast. r 1 = r 2 ], on a n = A r n 1 + B r n 2, (n N +) [vast. a n = (A n + B)r n 1, (n N +)] rekursioyhtälön (5.4) yleinen ratkaisu. Huom. 1. Edellä A ja B ovat (vapaita) reaalilukuparametreja, jotka voidaan tarvittaessa alkuehdolla kiinnittää. Usein joudutaan etsimään rekursioyhtälöiden (5.2) ja (5.4) yksityisratkaisuja annetulla alkuehdolla. Ensimmäisen kertaluvun tapauksessa tarvitaan alkuehto a 1 = b 1, missä b 1 on annettu reaalilukuvakio. Tällöin 5.2 saa muodon { a 1 = b 1 (5.6) a n+1 = c a n (n N + ). Nyt muodostetaan aluksi yleinen ratkaisu (5.3), jossa sitten a 1 korvataan luvulla b 1. Toisen kertaluvun tapauksessa yksityisratkaisun löytämiseksi tarvitaan kaksi alkuehtoa a 1 = b 1 ja a 2 = b 2, missä b 1 ja b 2 ovat reaalilukuvakioita. Yhtälö (5.4) saa nyt muodon { a 1 = b 1, a 2 = b 2 (5.7) a n+2 = c 1 a n+1 + c 2 a n (n N + ). Taas muodostetaan ensin (5.2):n yleinen ratkaisu. Jos karakteristisen yhtälön (5.5) juuret ovat erisuuret (eli r 1 r 2 ), ratkaistaan reaalilukuparametrit A ja B yhtälöryhmästä b 1 = A r 1 + B r 2, b 2 = A r1 2 + B r2 2. Olkoot A = A 0 ja B = B 0 saadut arvot. Tällöin a n = A 0 r1 n +B 0 r2 n, (n N +) on alkuarvoyhtälön (5.7) ratkaisu. Tapauksessa r 1 = r 2 vakiot A ja B ratkaistaan yhtälöryhmästä b 1 = (A + B) r 1, b 2 = (2A + B) r1 2 ; oletetaan, että parametreille A ja B saadaan arvot A = A 0 ja B = B 0. Tällöin a n = (A 0 n + B 0 ) r1 n, (n N +) on alkuarvoyhtälön (5.7) ratkaisu. Esim. 10. Olkoon (a n ) n=1 lukujono, missä a n+2 = 7 a n+1 12 a n (n N + ). Määritä a) yo rekursioyhtälön yleinen ratkaisu. b) ratkaisu alkuehdolla a 1 = 2, a 2 = 17. 91

Esim. 11. Herra Stackenboom, Folornian yliopiston (University of Folornia) perustaja ja rahoittaja, paljasti miten hänestä tuli miljonääri. Hän aloitti tyhjästä ja tehtyään työtä vuoden, hänellä oli koossa yksi dollari. Toisen vuoden jälkeen koossa oli viisi dollaria. Tämän jälkeen hän jokaisen vuoden aikana osti tavaroita kuusi kertaa suuremmalla summalla kuin hänellä oli koossa edellisen vuoden alussa ja myi ne hintaan joka oli neljä kertaa suurempi kuin summa, joka hänellä oli ansaittuna kuluvan vuoden alussa. Olkoon b n herra Stackenboomin ansaitsema rahasumma n. vuoden lopussa. Määritä rekursioyhtälö jonolle (b n ) n=1 ja ratkaise se. Kuinka monen vuoden päästä herra Stackenboomista oli tullut miljonääri? Esim. 12. Jokaisella n N + olkoon a n sellaisten binaariaakkoston pituutta n olevien sanojen lukumäärä, joissa ei esiinny kahta peräkkäistä nollaa. Määritä rekursioyhtälö a n :lle ja ratkaise se. Olkoot c, c 1 ja c 2 reaalilukuvakioita ja f : N + R funktio. Tällöin a n+1 = c a n + f(n) (n N + ) (5.8) on 1. asteen (yleinen) lineaarinen rekursioyhtälö. Vastaavasti a n+2 = c 1 a n+1 + c 2 a n + f(n) (n N + ) (5.9) on 2. asteen (yleinen) lineaarinen rekursioyhtälö. Yhtälön (5.8) ratkaisu on a n = h 1 (n) + d 1 (n) (n N + ) (5.10) missä h 1 (n) on yhtälöä (5.8) vastaavan homogeenisen lineaarisen rekursioyhtälön yleinen ratkaisu ja d 1 (n), (n N + ) on rekursioyhtälön (5.8) mikä tahansa erikoisratkaisu. Edelleen yhtälön (5.9) ratkaisu on a n = h 2 (n) + d 2 (n) (n N + ) (5.11) missä h 2 (n) on yhtälöä (5.9) vastaavan homogeenisen lineaarisen rekursioyhtälön yleinen ratkaisu ja d 2 (n), (n N + ) on rekursioyhtälön (5.9) mikä tahansa erikoisratkaisu. Yhtälön (5.8) tai (5.9) erikoisratkaisua etsittäessä voidaan usein soveltaa ns määräämättömien kertoimien menetelmää. Toinen mahdollisuus on käyttää ns generoivien funktioiden teoriaa, johon emme kuitenkaan tässä yhteydessä puutu. Esitämme seuraavassa määrämättömien kertoimien menetelmän yhtälön (5.9) erikoisratkaisun löytämiseksi. Vastaavalla tavalla, tosin jonkin verran yksinkertaisemmin, saadaan rekursioyhtälön (5.8) erikoisratkaisu. 92

Määräämättömien kertoimien menetelmä Aluksi on syytä huomata, että rekursioyhtälön (5.9) ratkaisu riippuu voimaperäisesti funktiosta f : N + R. Ratkaisu on olemassa vain sangen rajatulle joukolle funktioita f. Oletetaan seuraavassa, että rekursioyhtälössä (5.9) on f(n) summa, ja että tämän summan tekijät ovat (i) n:n polynomeja P (n); tai (ii) eksponenttilausekkeita a q n, missä luvut a, q 0; tai (iii) polynomien ja eksponenttilausekkeiden tuloja. Huomattakoon, että mikä tahansa muotoa (i), (ii) tai (iii) oleva tekijä voidaan esittää muodossa P (n)q n, kun n:n polynomi P (n) ja eksponenttifunktion kantaluku q sopivasti valitaan. Valitsemalla q = 1, saadaan tapaus (i); jos taas valitaan P (n) a, saadaan tapaus (ii). Nyt yhtälön (5.9) ratkaisussa (5.11) saadaan h 2 (n) aina määrättyä; se on Lauseen 1 antamaa muotoa. Ratkaisun d 2 (n) löytämiseksi käytetään yritettä. Yrite muodostetaan seuraavasti. f(n):n tekijä vastaava tekijä yritteessä eksponenttilauseke a q n A q n m. asteen polynomi P (n) A 0 n m + A 1 n m 1 + + A m 1 n + A m q n P (n) q n (A 0 n m + A 1 n m 1 + + A m 1 n + A m ) Yrite on tekijöidensä summa. Saatu yrite sijoitetaan yhtälöön (5.9) ja ratkaistaan määräämättömät kertoimet (edellisessä taulukossa A, A 0, A 1,..., A m edustavat määräämättömiä (realiluku)kertoimia). Menetelmä johtaa aina tulokseen mikäli seuraava otetaan huomioon. Olkoon g(n) = q n (A 0 n m + A 1 n m 1 + + A m 1 n + A m ) yritteen (joka on summa) mielivaltainen tekijä. Jos q on homogeenisen yhtälön karakteristisen yhtälön juuri, tulee yritteen tekijäksi valita g(n):n sijasta olla n p g(n), missä p N + on riittävän suuri, jotta yksikään tekijöistä n p q n, n p+1 q n, n p+2 q n,..., n p+m q n ei esiinny homogeenisen yhtälön yleisessä ratkaisussa. Esim. 13. Ratkaise rekursioyhtälö a 1 = 1, a n+1 = 3 a n + 2n, (n N + ) Esim. 14. (Hanoin tornit) oletetaan, että n pyöreää, samanpaksuista ja erisäteistä kiekkoa, joissa kussakin on reikä keskellä on asetettu sauvaan suuruusjärjestyksessä, suurin alimmaisena. Kuvassa 5.1 on n = 5. Tarkoitus on siirtää 93

1 2 3 Kuva 5.1: Hanoin tornit: n = 5 kiekot sauvaan 3 sauvaa 2 hyväksi käyttäen siten, että ne ovat sauvassa kolme suuruusjärjestyksessä (suurin alimmaisena) eikä siirtämisen aikana yhdessäkään sauvassa ole kiekkoja väärässä järjestyksessä. Olkoon a n tarvittavien siirtojen lukumäärä. Määritä a n :lle rekursioyhtälö ja ratkaise se. 5.5 Rekursiivisesti määritellyt funktiot ja rekursiiviset algoritmit Olemme nähneet, että funktioita voidaan määritellä rekursiivisesti. Jokseenkin kaikki nykyiset ohjelmointikielet sallivat rekursiivisten rakenteiden käytön. Tarkastellaan seuraavassa sitä, miten funktioita käsitellään pseudokoodissa. Ohjelmointikielessä käyttäjän määrittelemä funktio on tapana esittää funktioaliohjelmana. Aliohjelma muodostaa itsenäisen modulin, jota kutsutaan 'pääohjelman' jossakin osassa. Aliohjelma muistuttaa pääohjelmaa joissakin suhteissa, mutta erojakin löytyy. Pääohjelma saa syötteensä ohjelman ulkopuolelta 94

(näppäimistöltä tai muulta laitteelta), aliohjelman syöte taas tulee sitä kutsuvasta ohjelmamodulista ja syöte välittyy aliohjelmaan parametrien arvoina. Vastaavasti pääohjelman tuloste suuntautuu jollekin ohjelman ulkopuolla olevalle laitteelle, kun taas aliohjelman tuloste palautetaan kutsuvaan moduliin funktion arvona. Kun funktioita kirjoitetaan algoritmeiksi pseudokoodilla, emme välttämättä käytä syöte- ja tulostelausekkeita, vaan koodi voi alkaa funktion otsikolla, joka sisältää funktion nimen ja syöteparametrit. Esimerkiksi kertomafunktion f(n) = n!, (n N) pseudokoodi voitaisiiin esittää seuraavasti. KERTOMA(n) f=1 1. for i=1 to n do 2. f = i*f 3. return f Edellä esitetty algoritmi on pikemminkin iteratiivinen kuin rekursiivinen. Näin siitä huolimatta, että se taatusti nojaa kertoman rekursiiviseen määritelmään. Muutetaanpa nyt algoritmia siten, että se käyttää rekursiivista määritelyä vielä tehokkaammin, pannaan algoritmi viittaamaan itseensä ; korvataaan edellisen pseudokoodin for do silmukka if then else rakenteella Tällöin jos n = 0, on n! = 1, muussa tapauksessa n! = n (n 1)! KERTOMA_REK(n) if n==0 then 1. return 1 2. else 3. return n*kertoma_rek(n-1) Tässä on jo kyseessä rekursiivinen algoritmi, ei pelkästään rekursiiviseen määrittelyyn perustuva kaava. Rekursiivinen algoritmi se on siksi, että se viittaa itseensä, algoritmi kutsuu itseään. Esim. 15. Konstruoi rekursiivinen algoritmi rekursioyhtälön määrittämän funktion laskemiseksi. t(1) = 3 t n+1 = 2t(n) + n (n N + ) 95

Ratkaisu. Huomattakoon, että yo rekursioyhtölö todella määrittelee funktion t : N + N +. t(n) if n==1 then 1. return 3 2. else 3. return 2*t(n-1)+n Oletetaan nyt, että haluamme kirjoittaa algoritmin, joka tulostaa Esimerkin 15 määrittelemän jono m ensimmäistä termiä. Jos käytämme konstruoimaamme algoritmia, tämä voitaisiin tehdä esim. seuraavasti. Input: Luonnollinen luku m Output: Lukujonon {t(n)} m ensimmäistä termiä TULOSTA_LUKUJONO(m) 1. for i=1 to m do 2. x = t(i) 3. print x Edellä rakenneltu tulostusmenetelmä ei kuitenkaan ole kovin tehokas; jokaisella for do silmukan kierroksella t(n) rakennellaan rekursiivisesti uudelleen. Pyritään nyt kirjoittamaan koko algoritmi tulostuksineen päivineen rekursiivisesti. Tähän asti olemme tuumanneet rekursiota vain funktioaliohjelmien yhteydessä; rekursiotekniikkaa voidaan kuitenkin soveltaa paljon yleisemmin. Se edustaa kokonaan uudentyyppistä lähestymistapaa algoritmien suunnitteluun. Avainkysymys ongelman rekursiiviseen ratkaisemiseen on olettaa, että yksinkertaisempi tapaus ongelmasta on ratkaistu ja käsillä oleva tapaus palautetaan tähän yksinkertaisempaan tapaukseen. Sovelletaan nyt tätä ajattelutapaa esimerkkiimme. Meidän tulee vastata kysymykseen: Kuinka voimme tulostaa jonon m ensimmäistä termiä, jos jo olemme tulostaneet jonon m 1 ensimmäistä termiä?. Kun m > 1, vastaus kysymykseen on seuraava. 1. Tulostetaan jonon m 1 ensimmäistä termiä (käytäen algoritmia, joka meillä jo on). 2. Lasketaaan t(m). 3. Tulostetaan t(m). Herää kysymys, millä tavalla askel 2 edellä toteutetaan pseudokoodissamme. Tahdomme suorittaa toiminnon mahdollisimman tehokkaasti; jos nyt kutsuisimme konstruoimaamme rekursiivista algoritmia arvon t(m) laskemiseksi, toistaisimme edellä kuvatun tehottoman laskun. Meidän tulee askeleen 2 implementoinnissa käyttää askeleen 1 jo suorittamaa työtä eli (m 1):n al- 96

kion tulostusta. Siten algoritmimme tulee, tulostaessaan (m 1) ensimmäistä alkiota, myös palauttaa arvo t(m 1) kutsuvalle algoritmille. Algoritmi tarvitsee nimen, jotta sitä voitaisiin kutsua (TULOSTA_JONO_UUSI) ja tulostettavien alkioiden lukumäärän ilmoittavan parametrin (m). Jonon viimeisen termin ilmoittavan muuttujan (viimeinen_alkio) arvo voi toimia algorimin paluuarvona. Input: Luonnollinen luku m Output: Tulostaa lukujonon {t(n)} m ensimmäistä termiä, palauttaa m:nnen termin 1. TULOSTA_JONO_UUSI(m) 2. viimeinen_alkio = 3 3. if m>1 then 4. edellinen = TULOSTA_JONO_UUSI(m-1) 5. viimeinen_alkio = 2*edellinen + m 6. print viimeinen_alkio 7. return viimeinen_alkio Kun algoritmia kutsutaan parametrin m arvolla 1, se tulostaa lukujonon ensimmäisen alkion arvon 3 ja palauttaa sen. Jos oletamme, että kun m > 1, algoritmin kutsu TULOSTA_JONO_UUSI(m-1) tulostaa lukujonon m 1 ensimmäistä termiä ja palauttaa niistä viimeisen (eli lukujonon (m 1):nnen) termin, niin kutsuttaessa arvolla m algoritmi laskee edellisen rekursiivisen tulostuksen lisäksi lukujonon m:nnen termin ja tulostaa tämän. Koska algoritmi tulostaa parametrin arvolla 1 lukujonon ensimmäisen termin, se tulostaa kaikilla arvoilla m 1 jonon m ensimmäistä termiä. Esittämämme pseudokoodi ei voi jäädä yksin olemaan. Jonkun algoritmin tulee sitä kutsua, esimerkiksi: read m TULOSTA_JONO_UUSI(m) Esim. 16. Kuvaa edellisen algoritmin toimintaa syötteellä m = 3 Esim. 17. Laadi rekursiivinen algoritmi, joka etsii lukujen muodostamasta listasta pienimmän alkion. 97

6 Alkeislukuteoria (jaollisuus ja siihen liittyvät algoritmit) Kaikki olemme lapsuudesta asti tunteneet luonnolliset luvut. Siksipä voisi tuntua siltä, että verrattuna muihin lukuihin (negatiivisiin, rationaali-, irrationaali- ja kompleksilukuihin) niissä ei olisi paljoakaan uutta oppimista. Mikään ei liene kauemapana totuudesta; useat haastavimmista matematiikan avoimista ongelmista koskevat luonnollisia lukuja. Tässä luvussa käsitellään kuitenkin luonnollisten lukujen jaollisuuskysymyksiä perustasolla. 6.1 Lukuteoriasta yleisesti Lukuteoria on lähtökohtaisesti luonnollisten lukujen tutkimista. Usein tutkimusalue kuitenkin laajenee koskemaan negatiivisia kokonaislukuja ja rationaalilukuja; monet luonnollisten lukujen tarkasteluun soveltuvat tekniikat käyvät myös rationaaliluvuille. Edelleen useat irrationaali- ja kompleksilukuja koskevat tulokset vaativat kokonaislukujen tuntemusta. Luonnolliset luvut ovat sangen käyttökelpoisia laskennassa. Aikanaan arveltiin, että lukuteoria on matematiikan ala, jolla ei ole käytännön sovelluksia. 1 Tietokoneiden yleistyminen ja Internetin synty ovat muuttaneet tilannetta dramaattisesti. Salausmenetelmät ja virheitä korjaavien koodien suunnittelu sekä satunnaislukujen generointi ovat alueita, joissa lukuteoriaa voidaan suoraan soveltaa. Ei ole toisaalta yllättävä, että luonnolliset luvut, matematiikan ehkä tärkein diskreetti rakenne, näyttelee merkittävää osaa myös sellaisten laitteiden tutkinnassa, jotka prosessoivat tietoa diskreetillä tavalla. 1 Turun yliopiston pitkäaikainen matematiikan professori Kustaa Inkeri, eräs tunnetuimmista suomalaisista lukuteoreetikoista, oli sitä mieltä, että lukuteorialla ei ole käyttöä reaalimaailmassa, vaan se on kaunis teoria, joka soveltuu pelkästään akateemiseen tutkimukseen ja väitöskirjojen tekemiseen 98

6.2 Jaollisuus ja alkuluvut Aloitamme perustavaa laatua olevilla lukuteorian määritelmillä. Usein voimme pitäytyä pelkästään luonnollisissa luvuissa, mutta lähtökohtaisesti tarkastelemme kaikkien kokonaislukujen ominaisuuksia. Jakoalgoritmiin tutustutaan jo peruskoulun ala-asteella. Seraava usein käytetty tulos annetaan ilman todistusta. Huomaa, että lukujen a ja b ei oleteta olevan positiivisia kokonaislukuja. Lause 1. Olkoot a, b Z, a 0. Tällöin voidaan löytää sellaiset yksikäsitteiset luvut q Z ja r {0, 1,..., a 1}, että b = q a + r Edellisessä lauseessa a on jakaja, b jaettava ja r jakojäännös. Jakojäännöstä, joka saadaan, kun luku b jaetaan a:lla, merkitään b mod a; siis yllä b mod a = r. Vastaavasti voidaan asettaa b div a = q. Olkoot a ja b kokonaislukuja ja a 0. Tällöin a jakaa tasan luvun b, merk. a b, jos on olemassa sellainen kokonaisluku n, että b = n a. Jos a jakaa tasan b:n, sanomme myös, että a on b:n tekijä tai että b on a:n monikerta. Sitä, että a ei jaa tasan lukua b merkitään a b. Huom. 1. Luku a jakaa tasan luvun b täsmälleen silloin, kun b mod a = 0 Olkoot a, b ja c kokonaislukuja, a 0. Seuraavat faktat on helppo todistaa. 1. a 0, 1 b ja a a. 2. Jos a b, niin a bc. 3. Jos a b ja a c, niin a b + c. 4. Jos a b ja a c, niin a b c. 5. Jos a b ja b c, niin a c. 6. Jos a b niin ( a) b. 7. Jos a b ja b a, niin a = b tai a = b. Ykköstä suurempi kokonaisluku p on alkuluku, jos 1 ja p ovat sen ainoat positiiviset tekijät. Ykköstä suurempi kokonaisluku on yhdistetty luku, jos se ei ole alkuluku. Alkulukuja ovat esim. 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,... Yhdistetyt luvut kyetään esittämään pienempien luonnollisten lukujen tulona. Jos alkuluku p jakaa positiivisen kokonaisluvun n, sanomme, että p on 99

luvun alkulukutekijä. Selvästikin jokainen ykköstä suurempi kokonaisluku voidaan esittää alkulukujen tulona. Tällaista esitystä kutsutaan ko. luvun alkulukuesitykseksi. Esim. 1. Luvun 72 alkulukuesitys: 72 = 2 2 2 3 3 Lause 2 (Aritmetiikan peruslause). Ykköstä suuremman luonnollisen luvun alkulukuesitys on tekijöiden järjestystä vaille yksikäsitteinen. Fakta. Alkulukuja on ääretön määrä. 6.3 Suurin yhteinen tekijä ja Eukleideen algoritmi Olkoot a ja b luonnollisia lukuja, jotka molemmat eivät ole nollia. Lukujen a ja b suurin yhteinen tekijä on suurin sellainen luonnollinen luku m, että m a ja m b. Lukujen a, b N suurinta yhteistä tekijää merkitään syt(a, b). Määritelmän nojalla nähdään helposti, että jos a N + ja b = 0, on syt(a, b) = a. Olkoot a, b N +. Lukujen a ja b pienin yhteinen jaettava on pienin sellainen luku m N +, että a m ja b m. Lukujen a, b N pienintä yhteistä jaettavaa merkitään pyj(a, b). Esim. 2. Olkoot a, b N +. Miksi a) syt(a, b) yksikäsitteinen? b) pyj(a, b) on olemassa ja Millä tavalla kahden luvun suurin yhteinen tekijä voidaan määrätä? Yksi historian vanhimmista algoritmeista, ns. Eukleideen algoritmi, perustuu seuraavaan yksinkertaiseen havaintoon. Fakta. Olkoot a ja b kokonaislukuja. Tällöin aina, kun k Z, on lukujen a ja b yhteisten tekijöiden joukko sama kuin lukujen b ja a k b yhteisten tekijöiden joukko. Edellinen nähdään helposti seuraavasti. Olkoot a, b ja k kokonaislukuja. Jos d Z jakaa tasan a:n ja b:n (eli on a:n ja b:n yhteinen tekijä), se taatusti jakaa tasan myös k b:n ja siten erotuksen a k b ja on siten lukujen b ja a kb 100

yhteinen tekijä. Jos taas d Z jakaa tasan b:n ja a k b:n, se jakaa tasan myös k b:n ja siten luvun a = (a k b) + k b. Tällöin d on lukujen a ja b yhteinen tekijä. Nyt voimme palauttaa kahden positiivisen kokonaisluvun suurimman yhteisen tekijän laskemisen pienempien lukujen syt:n laskemiseen. Olkoot a, b N +, a b. Olkoot edelleen q N + ja r {0, 1,..., b 1} ne yksikäsitteiset luvut, joille a = q b + r. Yllä esitetyn faktan nojalla syt(a, b) = syt(b, r). Olkoot a, b N+. Oletetaan, että a b > 0. Jos b a, niin syt(a, b) = b. Oletetaan, että b ei jaa tasan lukua a. Jakoalgoritmin nojalla voidaan löytää yksikäsitteiset luonnolliset luvut k, q 0, q 1,..., q k+1, r 0, r 1,..., r k, joille a = q 0 b + r 0 0 < r 0 < b b = q 1 r 0 + r 1 0 < r 1 < r 0 r 0 = q 2 r 1 + r 2 0 < r 2 < r 1 (6.1) r k 2 = q k r k 1 + r k 0 < r k < r k 1 r k 1 = q k+1 r k. Edellä esitetyn nojalla syt(a, b) = syt(b, r 0 ) = syt(r 0, r 1 ) = = syt(r k 1, r k ) = syt(r k, 0) = r k. Esim. 3. Määritä Eukleideen algoritmin avulla syt(2093, 836). Ratkaisu. Käytetään Eukleideen algoritmia: Siispä syt(2093, 836) = 1. 2093 = 2 836 + 421 (1) 836 = 1 421 + 415 (2) 421 = 1 415 + 6 (3) 415 = 69 6 + 1 (4) 6 = 6 1 + 0 Seuraavaksi esitetään kolme algoritmia (kaksi iteratiivista ja yksi rekursiivinen) suurimman yhteisen tekijän määrittämiseksi. 101

Input: Luonnolliset luvut a ja b Output: Lukujen a ja b suurin yhteinen tekijä EUKLEIDES1(a,b) 1. while b!= 0 do 2. temp = b 3. b = a mod b 4. a = temp 5. return a Eukleideen algoritmi voidaan toteuttaa pelkällä vähennyslaskullakin. Input: Luonnolliset luvut a ja b Output: Lukujen a ja b suurin yhteinen tekijä EUKLEIDES2(a,b) 1. while b!= 0 do 2. // Vaihdetaan a ja b tarvittaessa 3. if a < b then 4. temp = a 5. a = b 6. b = temp 7. 8. temp = b 9. b = a - b 10. a = temp 11.return a Rekursiivinen pseudokoodi suurimman yhteisen tekijä määrittämiseksi on seuraavanlainen. Input: Luonnolliset luvut a ja b Output: Lukujen a ja b suurin yhteinen tekijä EUKLEIDES3(a,b) 1. if b == 0 then 2. return a 3. else 4. return EUKLEIDES3(b,a mod b) Yhtälöryhmässä 6.1 on r k = r k 2 q k r k 1, r k 1 = r k 3 q k 1 r k 2,..., r 2 = r 0 q 2 r 1, r 1 = b q 1 r 0 ja r 0 = a q 0 b. Näiden yhtälöiden avulla voimme löytää sellaiset kokonaisluvut x 0 ja y 0, että syt(a, b) = a x 0 + b y 0. Esim. 4. Määritä sellaiset luvut x 0, y 0 Z, että syt(2093, 836) = 2093 x 0 + 836 y 0 (vrt. edellinen esimerkki). 102

Ratkaisu. Käytetään Eukleideen algoritmia alhaalta ylöspäin (kts. Esim. 3). 1 = 415 69 6 (yhtälö (4)) = 415 69 (421 415) = 70 415 69 421 (yhtälön (3) perusteella 6 = 1 421 415) = 70 (836 421) 69 421 = 70 836 139 421 (yhtälön (2) perusteella 415 = 836 1 421) = 70 836 139 (2093 2 836) = 348 836 139 2093 (yhtälön (1) perusteella 421 = 2093 2 836) Saadaan 1 = 2093 ( 139)+836 348, joten voidaan valita (x 0, y 0 ) = ( 139, 348). Olkoot a, b ja c sellaisia kokonaislukuja, että joko a 0 tai b 0. Väitämme, että yhtälöllä a x + b y = c (6.2) on kokonaislukuratkaisu jos ja vain jos syt(a, b) jakaa tasan luvun c. Oletetaan aluksi, että yhtälöllä 6.2 on kokonaislukuratkaisu; olkoot x 0 ja y 0 sellaisia kokonaislukuja, että a x 0 + b y 0 = c. Vuorenvarmasti syt(a, b) jakaa em. yhtälön vasemman puolen a x 0 + b y 0, joten se jakaa myös sen oikean puolen puolen c. Siten, jos yhtälöllä 6.2 on kokonaislukuratkaisu, on voimassa syt(a, b) c. Oletetaan sitten, että syt(a, b) jakaa tasan luvun c. Olkoon k Z sellainen, että c = k syt(a, b). Aikaisemmin esitetyn nojalla voidaan löytää sellaiset kokonaisluvut, x 1, y 1, että a x 1 + b y 1 = syt(a, b). Selvästi a (k x 1 ) + b (k y 1 ) = k syt(a, b) = c, joten x 0 = k x 1, y 0 = k y 1 on yhtälön 6.2 ratkaisu. Esim. 5. Onko seuraavilla yhtälöillä kokonaislukuratkaisuja? a) 3024 x + 2076 y = 12 b) 3024 x + 2076 y = 36 c) 3024 x + 2076 y = 10. Myönteisessä tapauksessa määritä yksi ratkaisu. Ratkaisu. Käytetään Eukleideen algoritmia luvun syt(3024, 2076) määrittämiseksi. Tämän jälkeen voidaan tarkastaa jakaako syt(3024, 2076) yhtälöiden 103

a, b ja/tai c oikeat puolet. 3024 = 1 2076 + 948 (1) 2076 = 2 948 + 180 (2) 948 = 5 180 + 48 (3) 180 = 3 48 + 36 (4) 48 = 1 36 + 12 (5) 36 = 3 12 + 0 Siispä syt(3024, 2076) = 12. Esitetään nyt syt(3024, 2076) lukujen 3024 ja 2076 lineaarisena yhdelmänä. 12 = 48 1 36 (yhtälö (5)) = 48 1 (180 3 48) = 4 48 180 (yhtälön (4) perusteella 36 = 180 3 48) = 4 (948 5 180) 180 = 4 948 21 180 (yhtälön (3) perusteella 48 = 948 5 180) = 4 948 21 (2076 2 948) = 46 948 21 2076 (yhtälön (2) perusteella 180 = 2076 2 948) = 46 (3024 1 2076) 21 2076 = 46 3024 67 2076 (yhtälön (1) perusteella 948 = 3024 1 2076) Saadaan 12 = 3024 46 + 2076 ( 67). a) On ratkaisu, koska syt(3024, 2076) jakaa tasan yhtälön oikean puolen 12. Edellisen nojalla esim. (x 0, y 0 ) = (46, 67) on ratkaisu. b) On ratkaisu, syt(3024, 2076) 36. Esim. (x 1, y 1 ) = (3 46, 3 ( 67)) = (138, 201) on ratkaisu. c) Ei ole ratkaisua: luku syt(3024, 2076) = 12 ei jaa tasan lukua 10. Olkoot edelleen a ja b sellaisia kokonaislukuja, että joko a 0 tai b 0. Tarkastellaan joukkoa A = { n n N + ja on olemassa sellaiset x, y Z, että n = a x + b y}. Aikaisemmin esitetyn nojalla A = {k syt(a, b) k N + }. Siten syt(a, b) on pienin alkio joukossa A: syt(a, b) = min A. Oletetaan, että yhtälöllä 6.2 on ratkaisu (eli siis syt(a, b) c); olkoot x 0, y 0 Z lukuja, joille a x 0 + b y 0 = c. Yhtälön kaikki ratkaisut saadaan nyt yksityisratkaisun x 0, y 0 avulla. Yhtälön 6.2 kaikkien ratkaisujen joukko on Rat(a, b, c) = {(x 0 + n b syt(a, b), y a 0 n syt(a, b) ) n Z}. 104

Siis (x, y) Z Z on sellainen, että a x + b y = c jos ja vain jos (x, y) Rat(a, b, c). Olkoot a ja b positiivisia kokonaislukuja. Lukujen a ja b pienin yhteinen jaettava pyj(a, b) on pienin sellainen positiivinen kokonaisluku m, että sekä a että b jakavat tasan m:n (siis a m ja b m). Kokonaislukujen ominaisuuksien nojalla nähtiin helposti, että kahden positiivisen kokonaisluvun pienin yhteinen jaettava on olemassa ja yksikäsitteinen (miten?). Olkoot a, b N +. Tällöin pyj(a, b) = a b syt(a,b). 6.4 Kongruenssit Jaollisuuden käsite johtaa luontevasti kongruenssien tutkimiseen; modulo- eli kongruenssilaskenta on olennaisesti jakojäännöksillä laskemista. Alan pioneeri oli saksalainen matemaatikko Carl Friedrich Gauss (17771855) ja teoriaa käytetään laajasti tietokonesovelluksissa. Kongruenssiaritmetiikassa laskutoimitukset suoritetaan kokonaislukujen äärellisessä osajoukossa. Sinänsä modulolaskennan ajatuksessa ei ole mitään uutta, esim. kun aika ilmoitetaan tunneissa käytämme kokonaislukuja 1 12 (tai 1 24) ja kun 12 (vast. 24) on saavutettu, tuntien laskenta alkaa taas alusta. Toinen esimerkki modulolaskennasta on kokonaislukujen esittäminen tietokoneessa. Tutkimme luvussa 2 tilannetta, jossa ainoastaan luvut 8, 7,..., 6, 7 olivat esitettävissä tietokoneella. Määr. 1. Olkoon m positiivinen kokonaisluku. Kokonaisluvut a ja b ovat kongruentteja modulo m, jos m jakaa tasan lukujen a ja b erotuksen b a (eli siis m b a). Käytetään merkintää a b(mod m) tarkoittamaan sitä, että a ja b ovat kongruentteja modulo m. Heti nähdään, että a b(mod m) täsmälleen silloin, kun a:lle ja b:lle saadaan sama jakojäännös, kun ne jaetaan m:llä (eli silloin, kun a mod m = b mod m). Esim. 6. 7 4(mod 3) 11 19(mod 8) 35 14(mod 7) Olkoon nyt m joukon Z binaarirelaatio, joka määritellään ehdolla a m b, 105

jos a b(mod m) (eli jos m (b a)). Osoitamme seuraavassa, että m ekvivalenssirelaatio. Olkoot a, b, c Z. Reeksiivisyys a m a, koska m a a; Symmetrisyys Jos a m b, niin b m a, koska m b a m a b; ja Transitiivisuus Jos a m b ja b m c, niin a m c, koska m b a m c b m c a on Voimme kirjoittaa yo. ehdot myös seuraavasti: a a(mod m) aina, kun a Z. Jos a b(mod m), niin b a(mod m) aina, kun a, b Z. Jos a b(mod m) ja b c(mod m), niin a c(mod m) aina, kun a, b, c Z. Ekvivalenssiluokat: m (k) = {m n + k n Z}, missä k = 1, 2,..., m 1. Usein ekvivalenssiluokkaa m (k) merkitään [k] m tai [k] tai jopa vain symbolilla k ; näin silloin, kun sekaannusta ei pääse syntymään (eli m on tiedossa ja suoritetaan modulolaskentaa). Kongruenttisuuden lisäominaisuuksia: olkoot seuraavassa a, b, c, d Z ja m N +. 1. Jos a b(mod m) ja c d(mod m), niin a + c b + d(mod m). 2. Jos a b(mod m) ja c d(mod m), niin a c b d(mod m). 3. Jos a b(mod m) ja c d(mod m), niin a c b d(mod m). 4. Jos a c b c(mod m), niin a b(mod m syt(m,c) ). Yllä esitetyt ominaisuudet 1 ja 3 mahdollistavat ekvivalenssiluokkien modulo m yhteen- ja kertolaskun: [k] m + [j] m = [k + j] m ja [k] m [j] m = [k j] m. Yllä hakasulkeissa suoritetut yhteen- ja kertolaskut ovat tavanomaisia reaalilukujen yhteen- ja kertolaskuja. Jos samaistamme ekvivalenssiluokat [i] m luvun i kanssa, kun i = 0, 1,..., m 1, voimme samaistaa ekvivalenssiluokkien yhteenja kertolaskun jakojäännösten yhteen- ja kertolaskun kanssa määrittelemällä joukossa {0, 1,..., m 1} operaatiot ja seuraavasti: j k = (j + k) mod m ja j k = (j k) mod m. Yllä kaarisulkeissa suoritetut yhteen- ja kertolasku ( j + k ja j k ) ovat tavanomaisia relaalilukujen yhteen- ja kertolaskuja. Tarkastellaan vielä kongruenssiyhtälöä a x b(mod m), (6.3) 106

missä a, b Z ja m N + ovat annettuja vakioita ja x on (kokonaisluku)muuttuja. Kongruenttisuuskäsitteen määritelmän nojalla kokonaisluku x 0 on yhtälön 6.3 ratkaisu täsmälleen silloin, kun m (b a x 0 ). Tämä on yhtäpitävää sen kanssa, että voidaan löytää sellainen k Z, että b a x 0 = k m. Yhtälö b a x 0 = k m on yhtäpitävä yhtälön a x 0 + m k = b kanssa, joten jos yhtälöllä 6.3 on ratkaisu, täytyy (aikaisemmin esitetyn teorian nojalla ) luvun syt(a, m) jakaa tasan luku b. Ehto on selvästi myös riittävä. Jos nimittäin syt(a, m) b, voidaan löytää sellaiset x 0, k Z, että a x 0 + m k = b. Tällöin a x 0 b(mod m) eli yhtälöllä 6.3 on ratkaisuna x 0. Olemme osoittaneet oikeaksi seuraavan tosiasian. Fakta. Yhtälöllä 6.3 on ratkaisu jos ja vain jos syt(a, m) b. Oletetaan nyt, että x 0 Z on yhtälön 6.3 eräs yksityisratkaisu. Voidaan osoitaa, että yhtälön 6.3 kaikkien ratkaisujen muodostama joukko on } { x 0 + n m syt(a, m) n Z. 6.4.1 Pseudosatunnaislukujen generointi Joissakin sovelluksissa on tärkeää generoida satunnaisesti lukuja annetusta lukujoukosta; ajatus on tällöin se, että jokaisella joukon luvulla on yhtä suuri todennäköisyys tulla generoiduksi. Satunnaislukuja käytetään useissa tilanteissa, esim: - työkaluohjelmassa, jossa simuloidaan asiakkaiden saapumista palvelutiskille kuvaavaa satunnaisprosessia - valittaessa satunnaisotoksella ihmisiä tietystä populaatiosta mielipidekyselyä varten - generoitaessa satunnaisia syötteitä tietokoneohjelmalle Jos satunnaislukuja tarvitaan vain pieni määrä, voidaan niiden generointi suorittaa esim. heittämällä harhatonta m sivuista noppaa. Tällöin m on pieni positiivinen kokonaisluku. Jos taas tarvitaan suuri määrä satunnaislukuja, herää luonnollinen kysymys, josko niiden generointi voitaisiin suorittaa tietokoneella. Muistetaan, että tietokone lähtökohtaisesti on deterministinen laite annetusta syötteestä se aina tuottaa täysin ennustettavan tulosteen. On kuitenkin mahdollista ohjelmoida tietokone generoimaan lukujonoja, joilla on useita sellaisia ominaisuuksia, joita aitojen satunnaisprosessien tuottamilla lukujonoilla on. Tällä tavalla tietoko- 107

neella tuotettuja lukuja kutsutaan pseudosatunnaisluvuiksi. Seuraavassa kuvataan lyhyesti erästä käytössä olevaa pdseudosatunnaislukujen generointimenetelmää. Useimmat käytössä olevat pseudosatunnaislukujen generointimenetelmät perustuvat ideaan jossa generoidussa lukujonossa x 0, x 1, x 2,... on x 0 ns. siemen(luku) ja x n+1 saadaan luvusta x n annettua funktiota f käyttäen rekursiivisesti: x n+1 = f(x n ), kun n = 0, 1, 2,.... Edellä siemenen x 0 valitsee käyttäjä; eri siemenet antavat tavallisesti eri pseudosatunnaislukujonot, sama siemen tietysti saman jonon. Joissakin sovelluksissa on järkevää sitoa siemenen arvo aikaan, arvo on tällöin järjestelmän kellon antaman ajan funktio. Olkoot nyt m > 0, a ja c kokonaislukuja. Lineaarinen kongruenssimenetelmä (joka perustuu lukuihin m,a ja c ja siemeneen x 0 ) generoi pseudosatunnaislukuja joukosta {0, 1, 2,..., m 1} sääntöä x n+1 a x n + c (mod m) käyttäen. Kun ymmärrämme 'mod':n jakojäännösoperaatioksi, voimme kirjoittaa x n+1 = (a x n + c) mod m kun n = 0, 1, 2,.... Jos edellä c = 0, kyseessä on multiplikatiivinen kongruenssimenetelmä. Huomattakoon, että vakioiden a ja c valinta on tärkeä, kun halutaan, että jono käyttäytyy kuten todellinen satunnaislukujono. Havaitsemme, että heti kun sama luku esiintyy kahdesti jonosssa x 0, x 1, x 2,..., joudumme ikuiseen sykliin. Sykliin joudutaan tietysti jossain vaiheessa aina, koska m on äärellinen, mutta sitä on syytä välttää mahdollisimman pitkään. Tämä tapahtuu valitsemalla m sopivan suureksi ja vakiot a ja c huolellisesti. Mitä enemmän pseudosatunaislukuja tarvitaan, sitä suurempi tulee m:n olla. Näin siksi, että kykenemme generoimaan korkeintaan m pseudosatunnaislukua ennenkuin sykliin joutuminen tapahtuu. Voidaan osoittaa, että lineaarisessa kongruensimenetelmässä pseudosatunnaislukujonon satunnaisuus katoaa paljon ennenkuin m lukua on generoitu. Suositus onkin, että lukujen generointi lopetetaan viimeistään l askeleen jälkeen, kun l on syklin pituus. Kuinka suuri tulee luvun m sitten olla? Suositeltava m:n arvo on tietokoneessamme käytettävissä olevien etumerkittömien kokonaislukujen lukumää- 108

rä. Kuusitoistabittisessä koneessa luku on 2 16 = 65536, kolmekymmentäkaksibittisessä koneessa puolestaan 2 32 = 4294967296. Käytämme ensimmäisissä esimerkeissämme pientä m:n arvoa. Esim. 7. Lineaarista kongruenssimenetelmää käyttäen generoi pseudosatunnaislukujono, kun m = 16, a = 4, c = 3 ja siemenluku on x 0 = 1. Ratkaisu. Rekursioyhtälö on: x 0 = 1, x n+1 = (4 x n + 3) mod 16 (n = 0, 1, 2,...) Saamme jonon 1, 7, 15, 15,.... Vakioiden a ja c valinta Esimerkissä 7 on selvästi epätyydyttävä. Yritetään uudestaan. Esim. 8. Generoi pseudosatunnaislukujono lineaarista kongruenssimenetelmää käyttäen, kun m = 16, a = 3, c = 7 ja siemenluku on x 0 = 1. Ratkaisu. Rekursioyhtälö on: x 0 = 1, x n+1 = (3 x n + 7) mod 16 (n = 0, 1, 2,...) Saamme jonon 1, 10, 5, 6, 9, 2, 13, 14, 1,.... Esimerkissä 8 saamme generoitua kahdeksan lukua ennenkuin joudumme sykliin. Vieläkään emme kuitenkaan saa kaikkia kuuttatoista mahdollista lukua generoiduksi. Esim. 9. Lineaarista kongruenssimenetelmää käyttäen generoi pseudosatunnaislukujono, kun m = 16, a = 5, c = 11 ja siemenluku on x 0 = 1. Ratkaisu. Rekursioyhtälö on: x 0 = 1, x n+1 = (5 x n + 11)mod 16 (n = 0, 1, 2,...) Vastaava jono on 1, 0, 11, 2, 5, 4, 15, 69, 8, 3, 10, 13, 12, 7, 4, 1,.... Esimerkissä 9 saadaan generoiduksi kaikki luvut 0, 1, 2,..., 15. Tämä ei suinkaan ole ainoa ominaisuus, jota pseudosatunnaislukujonolta vaaditaan. Satunnaisuuden testaamiseen on olemassa erilaisia tilastollisia menetelmiä. 109

Edellisten esimerkkien valossa vakioiden a ja c valinta ei ole yksinkertainen tehtävä. Olemme korostaneet sen seikan tärkeyttä, että kaikki luvut joukossa {0, 1, 2,..., m 1} tulevat generoiduksi. Tämä on hiukan harhaanjohtavaa; huomattavasti tärkeämpää on saada generoiduksi jono, joka läpäisee tilastolliset satunnaisuustestit. Seuraavan esimerkin pseudosatunnaislukugeneraatoria voitaisiin soveltaa jo käytännössäkin. Esim. 10. Generoi 20 pseudosatunnaislukua generaattorilla x 0 = 2187, x n+1 = (2187 x n ) mod 65536. Ratkaisu. Havaitsemme, että 2 16 = 65536, joten menetelmä olisi sopiva valinta tietokoneessa, jossa luonnolliset luvut esitetään 16 bittiä käyttäen. Luvut ovat x 0 = 1, x n+1 = (4 x n + 3)mod 16 (n = 0, 1, 2,...) Saamme jonon 64377, 21171, 32561, 38811, 10537, 41286, 42849, 59819, 14297, 6867 10385, 36539, 22409, 53091, 45761, 5835, 47161, 52979, 62961, 4571. Tämä generaattori perustuu multiplikatiiviseen kongruenssimenetelmään eikä sillä saada kaikkia lukuja joukossa {0, 1, 2,..., 65535}. Voidaan osoittaa, että kaikki menetelmän antamat luvut ovat parittomia ja että noin neljännes yo joukon luvuista tulee generoiduksi. Nämä rajoitteet eivät ole vakavia; useimmissa käytännön sovelluksissa generoidut luvut tulisivat jaetuksi luvulla 65536, jolloin saadaan lähes tasaisesti jakautuneita lukuja väliltä (0, 1). Esim. 11. Muunna Esimerkissä 10 saadut luvut välin (suurin piirtein) tasaisesti jakautuneiksi luvuiksi väliltä (0, 1). Ratkaisu. Muuntaminen tapahtuu jakamalla kukin luvuista 65536:lla. Saadaan 0.982315, 0.323044, 0.496841, 0.592209, 0.160782, 0.629929, 0.653824 0.912766, 0.218155, 0.104782, 0.158463, 0.557541, 0.341934, 0.810104 0.698257, 0.089035, 0.719620, 0.808395, 0.960709, 0.069748. 110

7 Kombinatoriikka (lukumäärien laskeminen) 7.1 Kombinatoriikka ja laskenta tietokeoneella Kombinatoriikka on selllainen osa matematiikkaa, jossa lasketaan kuinka monella tavalla jokin prosessi voidaan toteuttaa. Tämäntyyppisiä tilanteita sattuu laskennassa usein. Tyypillinen tapaus on se, jolloin halutaan tietää kuinka monesti algoritmin tietyt askeleet suoritetaan. Tätä voidaan tarvita, kun esimerkiksi halutaan arvioida kauanko algoritmin ajo kestää. Seuraavassa esitellään muutamia perustason laskentatekniikoita, joita yllä kuvatuissa tilanteissa voidaan käyttää. 7.2 Summa- ja erotusperiaate Olkoot A ja B äärellisiä joukkoja. Summa- ja erotusperiaate kahdelle joukolle sanoo sen, että joukon A ja B unionin alkioiden lukumäärä (koko, kardinaliteetti) saadaan laskemalla yhteen A:n ja B :n alkioiden lukumäärä ja vähentämällä summasta A:n ja B :n leikkauksen alkioiden lukumäärä. Muodollisemmin: A B = A + B A B (7.1) Tulos voidaan helposti osoittaa induktiolla, A:n ja B :n alkioiden lukumäärän suhteen, mutta on se myös intuitiivisesti selvä. Kun A:n ja B :n koot lasketaan yhteen, tulevat leikkauksen A B alkiot lasketuksi kahteen kertaan, joten A B on syytä kertaalleen vähentää. Esim. 1. Erään koulutusohjelman 120:stä opiskelijasta 84 osaa ohjelmoida Ckielellä ja 66 Javalla. Jos 45 osaa ohjelmoida sekä C:llä että Javalla, niin kuinka moni ei osaa ohjelmoida kummallakaan? 111

Kombinatoriikan summaperiaate. Jos toiminto A voidaan suorittaa m :llä eri tavalla ja toiminto B voidaan suorittaa n:llä, A:n suorittamisesta riippumattomalla tavalla, niin toiminto A tai B voidaan suorittaa m + n eri tavalla. Esim. 2. Jos opiskelijalle on tarjolla neljä eri tilastotieteen kurssia ja viisi eri taloustieteen kurssia, niin hän voi valita tilastotieteen tai taloustieteen kurssin yhdeksällä eri tavalla. Esim. 3. Olkoot A, B ja c äärellisiä joukkoja. Osoita, että A B C = A + B + C A B A C B C + A B C. Kombinatoriikan summaperiaate voidaan esittää joukoilla seuraavasti. Olkoot A ja B äärellisiä joukkoja joille A B =. Joukosta A voidaan valita alkio A eri tavalla ja joukosta B tietysti B eri tavalla. Alkio voidaan valita joukosta A tai B kaikkiaan A + B eri tavalla. 7.3 Tuloperiaate Oletetaan, että dokumentti voidaan tulostaa käyttäen viittä eri fonttia: Arial, Gothic, Courier, Times Roman ja Sans Serif. Oletetaan, että kukin fontti voidaan esittää kolmella tyylillä: normaali, lihavoitu ja kursiivi. Kuinka monella tavalla fontti ja tyyli voidaan valita? Vastaus on yksinkertainen; koska fontteja on viisi ja tyylejä kolme, voidaan fontti ja tyyli valita 5 3 = 15 eri tavalla. (Huomattakoon, että fontti tai tyyli voidaan kombinatoriikan summaperiaatteen nojalla valita 5 + 3 = 8 eri tavalla.) Esitetään edellinen esimerkki joukkojen avulla. Olkoon F fonttien ja T tyylien joukko. Fontti ja tyyli voidaan valita joukosta F T ; monellako tavalla tämä voidaan tehdä, eli mikä on joukon F T koko. On selvää, että F T = F T = 1 3 = 15. Kombinatoriikan tuloperiaate. Jos toiminto A voidaan suorittaa m:llä eri tavalla ja toiminto B tämän jälkeen n:llä, toiminnon A suorittamisesta riippumattomalla tavalla, niin toiminto A ja B voidaan suorittaa m n eri tavalla. Sama joukoilla. Olkoot A ja B äärellisiä joukkoja (niiden ei välttämättä tarvitse olla pistevieraita). Tällöin A B = A B. Kombinatoriikan tuloperiaatteen mukaisesti kahden äärellisen joukon A ja B karteesisen tulon A B 112

alkioiden lukumäärä saadaan kertomalla A:n alkioiden lukumäärä A jouikon B alkioiden lukumäärällä B. Yleisemmin: olkoot n N + ja A 1, A 2,... A n äärellisiä joukkoja. Tällöin A 1 A 2 A n = A 1 A 2 A n. Esim. 4. Eräässä tietokoneessa käyttäjätunnukset koostuvat kolmesta latinalaisen aakkoston suuresta kirjaimesta, joita seuraa kolmen numeron jono (esim. ABC123). a) Kuinka monella tavalla käyttäjätunnus voidaan valita? b) Kuinka monessa käyttäjätunnuksessa numero 0 esiintyy ainakin kerran? 7.4 Permutaatiot Tarkastellaan kysymystä kuinka moneen järjestykseen joukon alkiot voidaan asettaa. Alkioiden a, b ja c eri järjestykset ovat: abc, acb, bac, bca, cab, cba Alkioiden eri järjestyksiä kutsutaan niiden permutaatioiksi. Kuinka moneen järjestykseen n eri alkiota voidaan asettaa? Permutaation 1. alkio voidaan valita n eri tavalla, 2. alkio n 1 eri tavalla, jne..., (n 1). alkio kahdella eri tavalla, n. alkio yhdellä tavalla. Tuloperiaatteen nojalla permutaatioiden kokonaislukumäärä on n (n 1) (n 2) 2 1. Esim. 5. Kuinka monta permutaatiota (anagrammia, kirjainjärjestystä) on seuraavilla sanoilla? a) ANSWER b) PERMUTE c) LITTLE Tarkastellaan n:n alkion joukkoa, jossa on k :ta eri tyyppiä olevia objekteja, n, k N +, n k. Oletetaan, että tyyppiä j olevia objekteja on n j kappaletta, j = 1, 2,..., k, jolloin siis n 1 + n 2 + + n k = n. Kuinka moneen eri järjestykseen voidaan objektit asettaa, kun sovimme, että samantyyppiset objektit ovat samanlaisia, ts. niiden välillä ei voi havaita eroa. Olkoon nyt x järjestysten lukumäärä. Jos tyyppiä 1 olevat objektit korvataan n 1 :llä erilaisella, toisistaan (ja muista objekteista) poikkeavalla objektilla, saadaan uusista objekteista n 1! keskinäistä järjestystä ja uudessa joukossa n 1! x 113

järjestystä. Samalla tavalla korvaamalla tyyppiä 2 olevat objektit n 2 :lla uudella, toisistaan (ja muista objekteista) poikkeavalla objektilla, jne..., korvaamalla tyyppiä k olevat objektit n k :lla uudella toisistaan (ja muista objekteista) poikkeavalla objektilla, saadaan n:n alkion joukko, jolla on järjestyksiä tietysti n! kappaletta. Edelleen varmasti pätee x n 1!n 2! n k! = n!. Siispä x = n! n 1!n 2! n k!. Yleisempi ongelma syntyy, kun permutaatioita muodostetaan suuremmasta joukosta. Oletetaan, että valitsemme r alkiota n eri alkion joukosta (n > r) ja asetamme ne nostamisen mukaiseen järjestykseen. Monellako tavalla tämä voidaan tehdä? Ensimmäinen alkio voidaan valita n tavalla, toinen n 1 tavalla, jne..., (r 1). alkio n r + 2 tavalla ja viimein r. alkio n r + 1 eri tavalla. Siispä n:n suuruisen joukon r -permutaatioita on P (n, r) = n (n 1) (n 2) (n r + 1) = n! (n r)! kappaletta. Esim. 6. Osana markkinatutkimusta henkilöitä pyydetään valitsemaan kahdestakymmenestä suklaapatukasta viisi mieluisinta ja asettamaan ne vielä paremmuusjärjestykseen. Monellako tavalla kaikkiaan tämä on mahdollista tehdä? 7.5 Kombinaatiot Edellisessä kappaleessa permutaatioita generoidessa alkioiden poimimisjärjestyksellä on merkitystä. Käytännössä yleisempi on tilanne, jossa äärellisestä joukosta poimitaan alkioita eikä järjestykseen kiinnitetä huomiota, ainoastaan siihen, mitkä alkiot tulevat valituksi. Tällöin on kyse kombinaatio-ongelmasta. Tarkastellaan loton perusarvontaa, jossa 39 luvusta valitaan 7. Oikean lottorivin kannalta valitsemisjärjestyksellä ei ole merkitystä, ainoastaan mitkä seitsemän lukua tulevat valituksi. Monellako tavalla voidaan rivi valita? Mikäli lukujen valitsemisjärjestyksellä olisi merkitystä, vastaus edellisen kappaleen mukaisesti olisi selvä: P (39, 7) = 39! 32! 114

Selvää on että lottorivejä on vähemmän; itse asiassa jokaista lottoriviä kohden on olemassa 7! permutaatiota, koska jokainen (suusruusjärjestyksessä oleva) lottorivi voidaan asettaa 7! eri järjestykseen (eli poimia 7! eri järjestyksessä). Jos nyt merkitsemme lottorivien lukumäärää C(39, 7), täytyy siis olla C(39, 7), = P (39, 7) 7! = 39! 7!32! On tietysti selvää että edellä esitetty yleistyy, kun n:n alkion perusjoukosta poimitaan r:n alkion osajoukko (n r). Siten aina, kun n, r N ja n r, voidaan n:n alkion joukosta poimia r:n alkion osajoukko C(n, r), = P (n, r) r! = n! r!(n r)! (n, r N, n r) eri tavalla. Usein merkitään C(n, r) = ( n r) ja tätä lukua kutsutaan binomikertoimeksi. Tämmöinen nimittely johtuu meidän kaikkien tuntemasta(?) binomikaavasta lukujen algebrassa: (a + b) n = ( ) n 0 a n b 0 + ( ) n 1 a n 1 b 1 + ( n 2) a n 2 b 2 + + ( ) n n 1 a 1 b n 1 + ( ) n n a 0 b n toisin sanoen. (a + b) n = n k=0 ( ) n a (n k) b k k Esim. 7. Diskreettien rakenteiden probleemapankissa on 292 kysymystä. Jokaiseen loppukokeeseen valitaan sieltä satunnaisesti viisi kysymystä. Kuinka monta eri loppukoetta on mahdollista tehdä? Esim. 8. Organisaatioon perustetaan tasa-arvotyöryhmä johon tulee viisi naista ja kolme miestä. Kuinka monella tavalla työryhmä voidaan muodostaa, kun organisaatiossa on palkattuna 18 naista ja 23 miestä? 115

Esim. 9. Motoristi haluaa ajaa paikasta A paikkaan B käyttäen seuraavan kuvion sallimia reittejä. Oletetaan, että hän ei koskaan palaa takaisinpäin (eli siirry vasemmalle tai ylöspäin) reitillään. Monellako tavalla motoristi voi reittinsä valita? A B Binomikerroin toteuttaa kiinnostavia identiteettejä, esim. ( ) ( ) n n = (n, r N, n r) r n r Edelleen ( ) n r = ( ) n 1 + r 1 ( ) n 1 r (n, r N +, n r) Yllä esitetty yhtäläisyys auttaa meitä generoimaan koulusta tutun ns. Pascalin kolmion. 7.6 Sovellus: Otos palautuksella Tarkastellaan vielä n erilaisen objektin muodostamaa joukkoa ja oletetaan, että permutaatioita ja kombinaatioita muodostettaessa valittu objekti aina palautetaan alkuperäiseen joukkoon, jolloin se on mahdollista valita uudelleen. Kysymyksessä on tällöin otos palautuksella. Muodostettaessa r-permutaatiota (jossa siis valittujen alkioiden keskinäisellä järjestyksellä on merkitystä), voidaan 1. alkio valita n eri tavalla, 2. alkio taas n eri tavalla, jne..., r. alkio n eri tavalla. Kombinatoriikan tuloperiatteen nojalla saadaan tällöin r - permutaatioiden lukumääräksi U(n, r) = n r aina, kun n, r N +. 116

Esim. 10. Olkoon A aakkosto, jossa on n kirjainta, n N +. Muodostamme r:n kirjaimen sanoja, r N +. Kuinka monella tavalla voidaan sana muodostaa, kun sama kirjain voi esiintyä sanassa a) korkeintaan yhden kerran? b) Mielivaltaisen monta kertaa? Vielä viimeiseksi tarkastelemme n:n erilaisen objektin r-kombinaatioiden lukumäärää, kun otos suoritetaan palautuksella. Nyt objektien järjestyksellä ei ole merkitystä; oletetaan, että objektia 1 on nostettu k 1 kertaa, objektia 2 on nostettu k 2 kertaa jne..., objektia n on nostettu k n kertaa. Tässä tietysti k 1 + k 2 + k n = r. Kääntäen yksikäsitteisesti edellä kuvattua valintaa vastaa nollista ja ykkösistä koostuva jono, jossa ensin on k 1 ykköstä ja sen jälkeen nolla, sitten k 2 ykköstä ja sen jälkeen nolla, jne..., k n 1 ykköstä ja sen jälkeen nolla ja viimeiseksi k n ykköstä. Ykkösiä on jonossa r ja nollia n 1 kappaletta. Kaiken kaikkiaan tällaisia jonoja on ( ) n + r 1 r = (n r 1)! (n 1)!r! Esim. 11. Pullakaupassa myydään 20 eri lajia donitseja. Monellako tavalla voidaan 12 donitsia valita, kun samaa lajia voi valikoimassa olla useampi kappale ja jokaista lajia on saatavilla enemmän kuin tusina?. 117

7.7 Laatikkoperiaate Kombinatoristen tarkastelujemme lopuksi esitettävä periaate on varsin yksinkertainen havainto, jota voidaan kuitenkin käyttää hedelmällisesti ratkaistaessa monenlaisia ongelmia. Laatikkoperiaate: 'Jos m palloa asetetaan n:ään laatikkoon, ja m > n, niin johonkin laatikkoon tulee ainakin kaksi palloa.' Yleistetty laatikkoperiaate: 'Jos ainakin k n + 1 palloa asetetaan n:ään laatikkoon, niin johonkin laatikkoon tulee ainakin k + 1 palloa.' Näillä periaatteilla voidaan johtaa mm. seuraavien esimerkkien tulokset. Esim. 12. Kolmentoista ihmisen joukossa on aina kaksi, joiden syntynäpäivä on samassa kuussa. Esim. 13. Laatikossa on 12 paria erivärisiä sukkia ja sieltä poimitaan sukkia umpimähkään. Montako poimintaa täytyy suorittaa, jotta voidaan varmistua ainakin yhdestä oikeasta parista? Esim. 14. Joukosta {1, 2,..., 200} valitaan 101 eri lukua. Osoita, että näiden joukossa on ainakin kaksi keskenään jaotonta. Esim. 15. Osoita, että kuuden henkilön joukossa on aina kolmen ryhmä, jossa joko kaikki tuntevat toisensa tai kukaan ei tunne toistaan. 118

8 Verkkoteoriaa Käsite verkko (eli graa) viittaa visuaaliseen rakenteeseen, joka koostuu solmuista ja niitä yhdistävistä väleistä. Verkko on abstraktio, jonka avulla voidaan kuvata objekteja ja niiden välisiä suhteita. Tietokoneverkossa solmut edustavat isäntäkoneita ja välit koneiden välisiä yhteyksiä. Tieverkossa solmut voisivat olla kaupunkeja ja välit niitä yhdistäviä teitä. Symmetrinen binaarirelaatio voidaan kuvata graan avulla, ja mikä tahansa binaarirelaatio puolestaan voidaan esittää ns. suunnattuna verkkona. Tässä esitetään verkkojen perusominaisuuksia. Verkkoja tarkastellaan ohjelmoinnin ja algoritmien kannalta kurssissa Tietorakenteet ja algoritmit. 8.1 Verkkoteorian peruskäsitteet Aluksi määrittelemme verkon. Tässä käsiteltävät verkot ovat suuntaamattomia, ts. välin päätepisteet määrittävät välin riippumatta niiden järjestyksestä. Määr. 2. Verkko (eli graa ) on järjestetty pari G = (V, E, h), missä V on verkon solmujen joukko ja E on joukon V järjestämättömien parien osajoukko. E on verkon välien joukko. Huomaa, että verkon kahta solmua voi yhdistää useampi väli. Tällaisia välejä sanotaan rinnakkaisiksi. Joskus sallitaan myös välit solmusta itseensä; tällaista väliä kutsutaan silmukaksi. Verkko on yksinkertainen, jos siinä ei ole rinnakkaisia välejä eikä silmukoita. Tästä eteenpäin käsittelemme ainoastaan yksinkertaisia verkkoja. Olkoon e = {x, y}, missä x y, verkon väli. Sanomme, että x ja y ovat välin e päät ja että solmut x ja y toistensa naapureita. Yksinkertaisen verkon G = (V, E, h) solmun x aste on luku d G (x) = {y V {x, y} on verkon G väli} 119

Yksinkertaisessa verkossa solmun aste on siis siitä lähtevien välien lukumäärä. Yksinkertaisen verkon G = (V, E) komplementti on yksinkertainen verkko G c = (V, E ), missä E = { {x, y} x, y V x y {x, y} / E }. Lause 1. Äärellisessä verkossa solmujen asteiden summa on kaksi kertaa välien lukumäärä. Siis jos G = (V, E) on äärellinen, on yhtälö voimassa. Σ x V d G (x) = 2 E Seuraus 1. Äärellisessä verkossa on paritonasteisten solmujen lukumäärä parillinen. Yksinkertainen verkko G = (V, E) on täydellinen, jos {x, y} E aina, kun x, y V, x y. Verkon G = (V, E) polku on (mikä tahansa) jono ρ = (x 0, e 1, x 1,..., e n, x n ), missä n N, x 0, x 1,..., x n V ja {x i 1, x i } E, kun i = 1, 2,..., n. Edellä n on polun ρ pituus, merk. ρ. Sanomme, että x 0 on polun ρ alkusolmu ja x n sen loppusolmu. Polku ρ kulkee solmujen x 0, x 1,..., x n kautta ja se on polku solmusta x 0 solmuun x n, merk. ρ : x 0 x n. Verkon G = (V, E, h) polku ρ = (x 0, e 1, x 1,..., e n, x n ) on 1. yksinkertainen, jos x 0, x 1,..., x n ovat kaikki eri solmuja; 2. avoin, jos x 0 x n ; 3. suljettu eli piiri, jos x 0 = x n ; 4. triviaali, jos n = 0; ja 5. sykli, jos n > 0, x 0 = x n ja x 0, x 1,..., x n 1 ovat kaikki eri solmuja. Verkko G on yhtenäinen, jos jokaisella G:n solmuparilla x, y on olemassa polku solmusta x solmuun y. Esim. 1 (Königsbergin sillat). Onko Königsbergissä (kts. Kuva 8.1) mahdollista löytää yhtenäinen reitti, jossa kukin silta ylitetään täsmälleen kerran? Verkkoteoreettisesti: onko kuvan 8.2 verkossa polkua, jossa kukin väli esiintyy täsmälleen kerran? 120

Kuva 8.1: Königsbergin sillat Kuva 8.2: Königsbergin sillat: verkko 121