Jorin jutut / ohjelmointi

Liukuluku - mikä on, miten niillä lasketaan?

Tämä kirjoitus yrittää selittää, mikä on liukuluku. Tarkoitus ei ole kertoa asiaa tarkasti, vaan ymmärrettävästi. Sen vuoksi mm. esimerkkinä käytetään 10-lukujärjestelmän mukaista "liukulukua", vaikka todellisuudessa tietokone käyttää 2-kantaista lukujärjestelmää.

Liukuluku tarkoittaa tapaa esittää luku arvon ja suuruusluokan yhdistelmänä. Esimerkiksi "34 miljoonaa" on yhdistelmä arvosta '34' ja suuruusluokasta 'miljoona'. Itse sitä huomaamattamme laskemme usein eräänlaisilla liukuluvuilla: "Perunat 12 markkaa, silakat 14 markkaa, yhteensä 26 markkaa; kaupungintalon laajennus 12 miljoonaa, paloaseman kunnostus 14 miljoonaa, yhteensä siis 26 miljoonaa markkaa."

Oletetaan, että arvo voi olla väliltä -999 .. 999 ja suuruusluokka kymmenen potensseina väliltä -9 .. 9. Esimerkiksi 0.0342 esitetään silloin muodossa 342×10^-4, siis arvo 342 ja suuruusluokka -4. Toinen tapa esittää sama luku olisi 034×10^-3 tai 003×10^-2, mutta tässä ei ole mieltä, koska luvun tarkkuus olisi huonompi. Kutsumme muotoa, jossa tarkkuus on suurin mahdollinen normaalimuodoksi. Tästä esitystavasta seuraa monia normaalista matematiikasta poikkeavia asioita.

Liukulukuesityksen rajoitukset

On olemassa suurin luku, joka voidaan esittää, 999×10^9. On olemassa myös pienin nollaa suurempi luku, 100×10^-9 (kun siis oletamme, että luvun pitää olla normaalimuodossa). Samalla tavoin on tietysti rajoitettu myös negatiiviset luvut tietylle välille.

Esitystavalla ei päästä mielivaltaiseen tarkkuuteen. Yksi kolmasosa on 333×10^-3, eli toisin sanottuna luku katkaistaan kolmen desimaalin tarkkuuteen. Luvun tarkkuus riippuu sen suuruusluokasta. Välillä 100 .. 999 voimme ilmaista luvun ykkösen tarkkuudella, 123×10^0 ja 124×10^0 eroavat toisistaan yhdellä. Välillä 10000 .. 99999 voimme puhua vain satojen tarkkuudesta, 123×10^2 ja 124×10^2 eroavat toisistaan sadalla. Vastaavasti välillä 0.0100 .. 0.0999 tarkkuus on 0.0001.

Outoa matematiikkaa

Liukulukujen yhteenlaskussa pitää lukujen suuruusluokat muuttaa samoiksi, samalla tavalla kuin käsin laskettaessa desimaalipilkut laitetaan allekkain. Esimerkiksi

  123×10^1 + 123×10^0
= 123×10^1 + 012×10^1
= 135×10^1           

Välillä luku esitettiin ei-normaalissa muodossa. Kertolasku on yksinkertaisempaa, arvot kerrotaan keskenään ja suuruusluokat summataan:

  123×10^2 * 345×10^5
= (123*345)×10^(2+5) 
= 42435*10^7         
= 424×10^9           

Välitulos oli jälleen normaalimuodosta eroava.

Suuruusluokaltaan paljon pienemmän luvun lisääminen ei vaikuta mitenkään:

  234×10^5 + 567×10^2
= 234×10^5 + 000×10^5
= 234×10^5           

Toisaalta kahden pienen luvun summa voi olla riittävä kasvattamaan isompaa lukua:

  (567×10^2 + 456×10^2) + 234×10^5
= 102×10^3 + 234×10^5             
= 001×10^5 + 234×10^5             
= 235×10^5                        

Siispä normaalit laskusäännöt eivät aina päde, tässäkin yhteenlaskujärjestyksellä on merkitystä! (A+B)+C ei olekaan ole yhtäsuuri kuin A+(B+C).

Kahden melkein yhtäsuuren luvun vähennyslaskun tulos on epätarkka. 437×10^4 ja 435×10^4 on esitetty kolmen numeron tarkkuudella. Niiden erotus, 002×10^4, on normaalimuodossa 200×10^2. Todellinen tarkkuus on vain yksi numero, mutta sitä ei mitenkään näe luvusta. Ilmiö tulee esille mm. laskettaessa (A+X)-X, kun X on paljon suurempi kuin A. Esimerkki:

  (234×10^0 + 345×10^2) - 345×10^2
= (002×10^2 + 345×10^2) - 345×10^2
= 347×10^2 - 345×10^2 = 002×10^2  
= 200×10^0                        

ja toisaalta

  (267×10^0 + 345×10^2) - 345×10^2
= (002×10^2 + 345×10^2) - 345×10^2
= 347×10^2 - 345×10^2             
= 002×10^2                        
= 200×10^0                        

Eli alkuperäisestä luvusta jäi jäljelle vain eniten merkitsevä numero.

Välituloksen ylivuoto

Vaikka kaikki alkuarvot ja laskun lopputulos pystyttäisiin esittämään liukuluvuilla, jokin välitulos voi olla liian suuri lukualueelle. Esimerkiksi suorakulmaisen kolmion hypotenuusa lasketaan ottamalla neliöjuuri kateettien neliöiden summasta. Jos lyhyempien sivujen pituudet ovat 400×10^6 ja 300×10^6, on kateettien neliöiden summa 250×10^12, eli ei mahdu tässä käytettävään liukulukuesitykseen. Ongelma voidaan toisinaan kiertää. Merkitään tässä neliöjuuri X merkinnällä Sqrt(X) ja oletetaan, että A>B.

  Sqrt(A^2+B^2)         
= Sqrt((A^2)(1+B^2/A^2))
= A*Sqrt(1+(B/A)^2)     

Tässä esimerkkitehtävässä siis lasketaankin

  400×10^6 * Sqrt(1+ (300×10^6 / 400×10^6)^2)
= 400×10^6 * Sqrt(1+ (0.75 * 10^(6-6) )^2 )  
= 400×10^6 * Sqrt(1+ (0.75 * 10^0 )^2 )      
= 400×10^6 * Sqrt(1+ (750×10^-3)^2 )         
= 400×10^6 * Sqrt(1+ (562500*10^-6))         
= 400×10^6 * Sqrt(1+ (563×10^-3))            
= 400×10^6 * Sqrt(100×10^-2 + 563×10^-3)     
= 400×10^6 * Sqrt(100×10^-2 + 056×10^-2)     
= 400×10^6 * Sqrt(156×10^-2)                 
= 400×10^6 * 124×10^-2                       
= (400*124)*10^(6-2)                         
= 49600*10^4                                 
= 496×10^6                                   

Tärkeät esille tulleet asiat tiivistettynä:

Linkkejä

Lyhyt johdatus äärettömyyteen on Jukka Korpelan kirjoitus siitä, miten ääretöntä käsitellään liukulukulaskennassa.


Kiitokset monille avuliaille ihmisille, jotka kertoivat mielipiteitään tämän dokumentin ulkoasusta eräässä uutisryhmäkeskustelussa

Kirjoitettu 2000-01-16, muokattu viimeksi 2000-01-20