Vapaaehtoinen, mutta suositeltava: Eri lukujärjestelmistä ja niiden aritmetiikasta

Luentomonisteesta tätä samaa asiaa löytyy tiiviisti luvusta 2.3.1. Lukujärjestelmät (s. 24, luku ja sivu tarkastettu 27.3.-17). Tässä osiossa toistetaan osa, mutta ei aivan kaikkea luentomonisteessa lukujärjestelmistä mainittuja asioita. Lue tarvittaessa kyseinen luku ennen kuin jatkat tästä eteenpäin.

Suorilta käsin saattaa olla mahdotonta tietää, mikä lukujärjestelmä milloinkin on kyseessä jos sitä ei erikseen sanota tai sitä ei voi kontekstista päätellä. Erilaisilla tekstinkäsittely- ja ladontajärjestelmillä tuotetuissa dokumenteissa saatetaan käyttää kantalukua ko. luvun alaindeksinä erottamaan eri lukujärjestelmät toisistaan. Tällä sivulla kirjoitetaan aina eksplisiittisesti, mikä järjestelmä on kyseessä. Lisäksi apuna käytetään seuraavaksi määriteltävää esitystapaa. Heksadesimaalijärjestelmän luvut on kirjoitettu alkavalla merkkiyhdistelmällä 0x, eli 0x1 ja 0xF2A, kuten C-kielessä ja sen perillisissä. Binäärijärjestelmän luvuilla on lopussa pieni b-kirjain, eli 1b ja 1010101b. Nämä merkinnät eivät liity luvuilla suoritettaviin laskutoimituksiin millään tavalla, vaan ne ovat ainoastaan havainnollistajia! Vastaavia merkintätapoja saatetaan käyttää maailmalla, joten ne on hyvä tietää. Kymmenjärjestelmän luvut esitetään 'normaalisti', eli 2, 101 ja 603. Lisäksi nyt mietitään lukuja vain ''matemaattisessa mielessä'' ja pysytään positiivissa kokonaisluvuissa, eli erilaiset tietokoneen sisäiset esitystavat ja negatiivisten lukujen esittämistavat jätetään huomiotta.

Selvyyden vuoksi mainittakoot, että tässä yhteydessä käytämme termiä numero kun tarkoitamme ''lukujärjestelmän mahdollisia kertoimia''. Esimerkiksi binäärijärjestelmä koostuu numeroista 0b ja 1b, kymmenjärjestelmä koostuu numeroista 0, 1, 2, 3, 4, 5, 6, 7, 8 ja 9 ja heksadesimaalijärjestelmässä on numerot 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE ja 0xF. Termiä luku käytämme kun nyt tarkoitamme ''numeroista tehtyä koostetta''. Lisäksi mainittakoon vielä se, että heksalukujen yhteydessä käytetään nyt ainoastaan isoja kirjaimia ja binääriluvuilla havainnolistamiseen pientä b-kirjainta.

Muunnoksia lukujärjestelmästä toiseen

Seuraavaksi on esimerkkejä ja harjoitteita lukujen muuttamisesta lukujärjestelmästä toiseen. Aluksi on (toivottavasti) riittävä määrä esimerkkejä, jonka jälkeen voi itsenäisesti kokeilla muunnoksia. Nämä harjoitteet eivät ole osa pakollista palautustehtävää, vaan ne on tarkoitettu oppimisen tueksi. Visuaalisten havainnolisteiden lisäksi erikseen mainitaan, mistä lukujärjestelmästä tehdään muunnos ja mihin lukujärjestelmään. Lisäksi mainittakkoon, että esitetyt menetelmät lukujärjestelmien vaihtoon eivät ole ainoita mahdollisia. Jos jo osaat jonkun toisen tavan mukaan muunnoksia, niin voit käyttää myös niitäkin. Muunnokset esitetään tässä niin, että lukujärjestelmästä, mistä muunnos tehdään on, aina vasemmalla ja lukujärjestelmä, mihin muunnetaan, on aina oikealla yhtäsuurusmerkistä. Esimerkeissä on myös kirjoitettu välivaihe auki. Kysymysmerkki tarkoittaa, että itse sopii harjoitella kyseistä suoritetta. Eksponentin merkkinä käytetään hattua (A.K.A. sirkumfleksiä) eli ^ -merkkiä.

Muunnos binäärijärjestelmästä kymmenjärjestelmään onnistuu helposti, kun lisäilee binääriluvun sijaintipaikan perusteella oikeat kakkosen potenssin yhteen:

110b = 1 * 2^2 + 1 * 2^1 + 0 * 2^0 = 4 + 2 + 0 = 6
10101b = 2^4 + 2^2 + 2^0 = 16 + 4 + 1 = 21
1b = ?
1001b = ?
1010b = ?
110101b = ?
111111b = ?

Muunnos heksadesimaalijärjestelmästä kymmenjärjestelmään toimii vastaavalla tavalla kuin binäärijärjestelmästä kymmenjärjestelmään. Erona vain on, että summaillaan luvun kuusitoista potensseja yhteen. Heksadesimaalijärjestelmästä pitää lisäksi muistaa, että numerot A, B, C, D, E ja F ovat myös pelissä mukana:

0x4 = 4 * 16^0 = 4
0xA = 10 * 16^0 = 10
0xF = 15 * 16^0 =15
0x10 = 1 * 16^1 + 0 * 16^0 = 16
0x12 = 1 * 16^1 + 2 * 16^0 = 18
0x110 = 16^2 + 16^1 = 272
0x23 = ?
0x16 = ?
0x2F = ?
0xBC = ?
0xEB = ?

Muunnos kymmenjärjestelmästä binäärijärjestelmään voi vaikuttaa aluksi haastavammalta kuin muunnos binäärijärjestelmästä kymmenjärjestelmään, mutta se vaatii vain vähän enemmän pähkäilyä ja mahdollisesti jonkun verran kokeilua. Esimerkiksi muunnettaessa kymmenjärjestelmän lukua 5 binäärijärjestelmään aloitamme miettimällä ''mikä kakkosen potenssi on suurempi kuin muunnettava luku, mutta sitä pienempi kakkosen potenssi on pienempi tai yhtäsuuri kuin muunnettava luku''. Tässä tapauksessa 2^3 eli luku 8 täyttää tämän ehdon. Tästä tiedämme, että muunnetussa luvussa tulee olemaan kolme numeroa, koska toinen, ensimmäinen ja ''nollas'' potenssi on mukana pelissä jollain tapaa. Tämän jälkeen mietimme, millä jäljelle jäävien kakkosten potenssien summalla tämän suurimman potenssin kanssa saadaan haluttu luku. Ainoa mahdollisuus on 2^2 + 2^0 eli alkuperäinen luku 5 kymmenjärjestelmässä:

1  = 2^0 = 1b
3  = 2^1 + 2^0 = 11b
12 = 2^3 + 2^2 = 1100b
13 = 2^3 + 2^2 + 2^0 = 1101b
110 = 2^6 + 2^5 + 2^3 + 2^2 + 2^1 = 110 1110b
1  = ?
8  = ?
10  = ?
53  = ?
302  = ?

Muunnos kymmenjärjestelmästä heksadesimaalijärjestelmään voidaan tehdä muutoin vastaavasti kuin binäärijärjestelmään. Esimerkiksi kymmenjärjestelmän lukua 53 muuttaessa heksadesimaalijärjestelmään huomataan ensin, että 16^2 = 256 menee yli eli muunnetussa heksadesimaaliluvussa on kaksi numeroa. Sitten kokeilun tai muun osaamisen kautta keksitään 3 * 16^1 + 5 * 16^0 = 53, eli muunnettu heksaluku on 0x35:

4 = 0x4
11 = 0xB
110 = 0x6E
15 = ?
33 = ?
53 = ?
117 = ?
256 = ?

Muunnos heksadesimaalijärjestelmästä binäärijärjestelmään pitäisi onnistua kivuttomasti kun huomaa, että 16 = 2^4. Tästä saadaan, että heksadesimaalijärjestelmän luvun numerot voi korvata vastaavilla binäärijärjestelmän luvuilla. Esimerkiksi heksadesimaalijärjestelmän luku CD voidaan ensin muuttaa numero kerrallaan vastaaviksi binäärijärjestelmän luvuiksi, eli 0xC = 12 = 1100b ja vastaavasti 0xD = 1101b. Tästä saamme suoraan binäärijärjestelmän luvun 11001101b:

0x2 = 10b
0x9 = 1001b
0x1E = 11110b
0xFF = ?
0x15 = ?
0xAD = ?
0x53 = ?
0x1A3 = ?

Binäärijärjestelmästä heksadesimaalijärjestelmään onnistuu käänteisesti vastaavalla tavalla kuin heksadesimaalijärjestelmästä binäärijärjestelmään. Esimerkiksi binäärijärjestelmän luku 10001010b saadaan numeroittain muuntaen 1000b = 8 = 0x8 ja 1010b = 10 = 0xA, joten muunnettu heksadesimaaliluku on 0x8A:

101b = 0x3
11011011b = 0xDB
1111b = ?
10001b = ?
11001100b = ?
10010010b = ?
111011010b = ?

Aritmetiikkaa eri lukujärjestelmillä

Seuraavaksi tarkastellaan plus- ja miinuslaskua eri lukujärjestelmissä. Mikäli päässälasku tuottaa hankaluuksia, niin kynällä ja paperilla suoritettu allekkainlasku toimii aivan samalla tavalla kuin kymmenjärjestelmässä. Laskiessa pitää vain muistaa käytetty kantaluku, eli esimerkiksi heksoina laskiessa ei ''pyöräytä'' numeroa ympäri ja laita muistinumeroa vielä numeron 9 jälkeen vaan jatkaa tilanteen vaatiessa sinne numeroon F asti.

Laske laskutoimitukset binäärijärjestelmän luvuilla:

1b + 1b = 10b
10b + 1b = 11b
111b + 11b = 1010b
10010b + 110010b = ?
11111b + 1b = ?
11001b + 110b = ?
10110b + 11001b = ?
1100111b + 100101b = ?
1001100b - 1000001b  = ?
11001111b - 101001b = ?
11101010b - 10110b = ?

Laske laskutoimitukset heksadesimaalijärjestelmän luvuilla:

0x4 + 0x3 = 0x7
0x6 + 0x6 = 0xC
0xD + 0x5 = 0x12
0x1B + 0x3A = ?
0xDD + 0x23 = ?
0x89 + 0xEB = ?
0x12 + 0x1E = ?
0x10+ 0x99 = ?
0xAAF - 0x4C1 = ?
0x1B8 - 0x73  = ?
0xDEF - 0xABC = ?

Kappalemäärien ja välien laskemisen erosta

Vielä tämän osion päätteeksi mainittakoon lukujärjestelmistä riippumaton ns. ''aidan välien'' ja ''aidan seipäiden'' laskemisen välinen ero. Tämä maininta saattaa tuntua irralliselta, mutta ohjelmoinnissa tämä ongelma tulee paikoitellen vastaan eri tilanteissa, luultavasti eri nimillä. Havainnollistetaan tätä ongelmaa esimerkiksi taulukkoindeksoinnilla. Olkoon meillä perustavanlaatuinen tietorakenteemme taulukko. Taulukossa on tässä tapauksessa vaikka kahdeksan alkiota, eli indeksit menevät nollasta seitsemään (kuten C:n sukuisissa kielissä esim. C#:ssa ja Javassa). Nyt itse ''ongelmaan'', eli montako taulukon alkiota on vaikka indeksien 3 ja 5 välillä? Nopeasti asiaa sen enempää ajattelmatta voisi laskea 5 - 3 = 2, mutta onhan siellä indeksit 3, 4 ja 5. Alkuperäinen laskumme laskee ''aidan välejä'', mutta nyt olimmekin kiinnostuneita ''aidan seipäistä''. Esimerkki on alkeellinen ja myöskin keinotekoinen, mutta vastaavanlainen tilanne tulee vastaa monimutkaisemmissakin tapauksissa (esim. pinomuistin osoitteita laskiessa). Emme mene tässä sen syvällisemmin tämän ongelman mihinkään matemaattiseen luonteeseen, mutta tämän(kin) kurssin materiaalissa tulee vastaan tilanteita, joissa kannattaa miettiä mitä oikeasti on laskemassa.

Reunahuomautus: Ainakaan tämän kurssin vastuuopettaja ei koskaan saa aikaan oikeata koodia kirjoittamatta paperille yksinkertaista esimerkkiä väleistä ja seipäistä. Todellinen välien määrä voi olla miljoonia, mutta riittää piirtää ihan muutama, että näkee vastauksen:

+------+------+------+------+   Ookke.. jos mulla on 4 alkiota, niin vika
| t[0] | t[1] | t[2] | t[3] |   on indeksissä 3 eli 4-1 ja jos laskisin
+------+------+------+------+   "aidanseipäitä", niin niitä olisi se 4 kpl.
                                Eli jos on 12345 alkiota, niin viimeinen
                                olis t[12344], jos olis N alkiota, niin
                                viimeinen olis N-1. OK.. sitten vasta
                                kajotaan koodiin, kun asia on selvä.

Vapaaehtoisen palautuksen kannalta oleelliset laskutoimitukset ovat seuraavaksi alla:

[luku1]: Muunna syntymävuotesi heksadesimaaliluvuksi


[luku2]: Laske käyttämällä edellisen muunnoksen tulosta
         [luku1] + 0xAB

[luku3]: Laske binäärijärjestelmän luvulla käyttäen edellisen kohdan tulosta. Ilmoita vastaus binäärilukuna.
         10101011b - [luku2]

[luku4]: Mikä luku tarvitsee lisätä tai poistaa edellisen kohdan
         vastauksesta [luku3], jotta saat taas syntymävuotesi? Jos jotain tarvitsee
         lisätä, laita vastaus muodossa +[luku4], jos taas vähentää laita vastaus
         muodossa -[luku4] ja kirjoita vastaus kymmenjärjestelmän lukuna

Laskutoimituksen osalta palautus tehdään siten, että kirjoitat alla olevan tekstin uuteen tiedostoon sanatarkasti (copy-paste ehkä rikkoo tai ehkä ei riko rivinvaihtoa riippuen toimintaympäristöstäsi, joten jos kopioit niin varmista että tiedosto varmasti näyttää oikean muotoiselta):

Muunnos heksadesimaalijärjestelmästä kymmenjärjestelmään: [luku1]
Laskutoimitusten tulokset: [luku2] [luku3] [luku4]

Korvaa saamasi vastaukset vastaavien ''muuttujien'' tilalle ja lukujärjestelmien osuus on palautusmuodossa.