torstai 6. heinäkuuta 2017

Rakensin laskimen. Mitä tarvitsin siihen?

Wolfram|Alpha on erinomainen työkalu: pitkälle kehittynyt symbolinen laskin ja tietopankki. Olen totta kai sen aktiivinen käyttäjä, ja yhteen Fermi-arvioblogaukseen kuluu kymmeniä ellei satoja hakuja. Tuloksia odotellessa ehtii kiinnittää huomiota yhteen asiaan... tuloksia joutuu odottelemaan. Monimutkaisiin laskuihin kuluvan ajan ymmärrän, mutta miksi helpot lausekkeet vaativat niin paljon aikaa?

Päätin siis jonkun aikaa sitten kokeilla rakentaa oman yksikkölaskimeni — sellaisen, joka korvaisi Alphan yksinkertaisissa laskutoimituksissa ja olisi paljon nopeampi. Sellaisia varmasti on paljon, mutta puolen ikäänsä ohjelmoineelle valmis ei kelpaa! Samalla nimittäin sain hyvän syyn luoda ensimmäisen pilvipalveluni, mitä olin halunnut tehdä jo pitkään.

Vajaan parin viikon työn tuloksena syntyi Aleph|Nolla. Se on kauttaaltaan ilmainen, kevyt ja käynnistymistä lukuunottamatta salamannopea (ilmaisen palvelutason huono puoli). Pienestä keskeneräisyydestä huolimatta se toimii kohtalaisesti. Alla kerron muutaman palasen siitä, millaista matematiikkaa työssä tarvitsin.

Algoritminen ajattelu

Tässä on syy, miksi kannatan ohjelmoinnin tuomista kouluihin. Koko palvelu ei ole kuin kasa peräkkäisiä vaiheita: muuta haku koneen ymmärtämään muotoon, muuta kaikki luvut perusyksiköihin, laske lauseke, muuta tulos sopivaan yksikköön, tee loput muunnokset, vertaa tunnettuihin lukuarvoihin, näytä tulokset käyttäjälle. Jokainen näistä vaiheista jakautuu edelleen pienemmiksi osiksi. Rakentaminen ja testaaminen on paljon helpompaa pala kerrallaan — jälkikäteen korjaamisesta puhumattakaan!

Monikaan ihmiselle selvä asia ei ole koneelle intuitiivinen, joten asioita täytyy osata ajatella eri tavalla. Kaikkein isoin esimerkki löytyy matemaattisista lausekkeista. Me näemme tämän:

\[ 10~\mathrm{N} + 5~\mathrm{kg} \cdot 9.81~\frac{\mathrm{m}}{\mathrm{s}^2} \]

Kone näkee tämän:

Ylösalaisin oleva puurakenne, jonka oksanhaarat vastaavat operaatioita lausekkeessa.

Graafiteoreetikot kutsuvat ylläolevaa puuksi. (Kannatan muuten myös biologian opetusta ja ulkona käymistä.) Jokainen "oksanhaara" vastaa operaatiota, kuten yhteen- tai kertolaskua. "Lehdet" puolestaan vastaavat lukuja tai yksiköitä. Kukin haara lasketaan laskemalla ensin siitä alkavat haarat ja sitten summaamalla/kertomalla/mitävain tulokset. Lopullinen tulos saadaan siis aloittamalla juuresta, etenemällä vuorollaan syvälle kumpaankin haaraan ja palaamalla takaisin.

Lausekkeen muuttaminen puuksi on hieman monimutkaisempi asia, joka toimii itse asiassa paljolti samalla periaatteella. Nerokasta on, että samoilla tekniikoilla voidaan tulkita myös ohjelmointikieliä ja muita tarkkaan määrättyjä kielioppeja. Lisää tästä löytää esimerkiksi hakusanoilla "recursive descent parser" ja "precedence parser".

Logaritmit ja vertailut

Vertailukohtia esittävä komponentti on yksinkertainen: sillä on lista tunnetuista luvuista ja se kokeilee jakaa tuloksen jokaisella niistä. Jos osamäärällä ei ole yksikköä, yksiköt ovat täsmänneet ja vertailu päätyy listalle.

Esimerkiksi pituudelle on kuitenkin kolmisenkymmentä vertailukohtaa. Haluan esittää enintään kolme lähintä lukua. Miten löydän lähimmät? (Kolme sekuntia aikaa lukea alaotsikko uudelleen.)

Logaritmilla tietysti. Lasken jokaisen kertoimen etäisyyden ykkösestä kaavalla $|\log(x) - \log(1)|$. Koska $\log(1)=0$, riittää järjestää tulokset suuruusjärjestykseen logaritmin itseisarvon mukaan. Sitten vain valitaan (enintään) kolme pienintä. Jo aiemmassa vaiheessa olen tiputtanut liian etäällä olevat tulokset: ne, joissa $x < 0.1$ tai $x > 10$.

Pikkaisen fysiikkaa

Yksiköillä leikkiminen on totta kai enemmän fysiikkaa kuin matematiikkaa. Matematiikassakin toki tulee käytännöllisiä tehtäviä, joissa luvut tarvitsevat yksiköitä ja viimeinen yksikkötarkastus saattaa pelastaa sensorin punakynältä. Eri muodoissa asiaa on taidettu käydä alakoulusta asti (ja silti se menee valitettavan monelta ohi). Säännöt siis ovat:

  1. Yksiköt tarraavat lukuihin ja niitä kerrotaan, jaetaan ja potenssiinkorotetaan ihan samoilla säännöillä.
  2. Eri yksiköitä ei voi laskea yhteen tai vähentää.
  3. Näiden sääntöjen rikkojat joko kuristetaan tai ammutaan aamunkoitteessa. (Hei Clasun lehtorit!)

Tieteessä käytettävä SI-järjestelmä koostuu seitsemästä perussuureesta. Kaikki loput yksiköt on johdettu näitä kertomalla ja jakamalla. Voiman yksikkö newton on $\mathrm{kg} \cdot \mathrm{m} \cdot \mathrm{s}^{-2}$, paineen yksikkö pascal puolestaan $\mathrm{N} / \mathrm{m}^2$. Lisäksi on valtava kasa muinaisia ja nykyisiä kerrannaisyksiköitä, kuten kuuttakymmentä sekuntia vastaava minuutti tai 2,54 senttimetrin suuruinen tuuma, sekä kourallinen millin kaltaisia etuliitteitä.

Yksiköillä pelaaminen on tämän pohjalta yksinkertaista. Ohjelma muuttaa jokaisen vastaantulevan yksikön perusyksiköiden kertolaskuksi, mahdollisesti etuliitteillä kertoen ja muunnoksilla pelaten. Sitten tapahtuu laskeminen, jossa yksikköpuuro sekoittuu — yksiköt kertovat ja kumoavat toisiaan. Lopuksi ohjelma yrittää tehdä osan muunnoksista takaperin, jotta tuloksesta tulisi mahdollisimman yksinkertainen.

Joillakin yksiköillä on merkityksiä, jotka eivät aina selviä perusyksiköiden kautta. Siksi Aleph|Nollassa on neljä ylimääräistä perusyksikköä. Radiaani ja steradiaani ovat kumpikin yksiköttömiä, mutta ensimmäinen elää kahdessa ja toinen kolmessa ulottuvuudessa. Niitä ei ole mielekästä muuntaa keskenään.

Toinen samanlainen pari ovat säteilyannoksen yksiköt gray ja sievert. Kumpikin on määritelty jouleina kilogrammaa kohti, mutta ensimmäinen muutetaan jälkimmäiseksi huomioimalla eri säteilytyyppien vaikutuskertoimet. Niitä ei voi muuntaa tietämättä säteilyn laatua ja kohdetta — virheellisen yksi yhteen -vastaavuuden käyttämisellä voi voittaa vihaisen soiton Säteilyturvakeskuksesta.

Logaritmit ja lukujen esittäminen

Loppuvaiheessa luvut pitää muuttaa ihmisen luettaviksi. Missä kohtaa kannattaa siirtyä tavallisesta luvusta kymmenpotenssimuotoon? (Vihje: luvun logaritmin itseisarvo ylittää rajan.) Entä kuinka monta desimaalia pilkun jälkeen tulee, jotta merkitsevien numeroiden määrä on vakio? (Vihje: vakio miinus luvun logaritmi.)

Näyttää vahvasti siltä, että olen keväästä asti kampanjoinut logaritmien puolesta. Ne ovat hyödyllisempiä kuin alkuun luulisi. Tarkkana sillä kurssilla!

Kaikki muut taidot

SI-järjestelmän perusyksiköt ovat metri, sekunti, ampeeri, kelvin, mooli, kandela ja kilogramma. Kyllä, kilogramma. Ainoa yksikkö, jonka nimessä on valmiiksi etuliite. Millisekunti on sekunnin tuhannesosa, mutta milligramma onkin kilogramman miljoonasosa. Argh.

Ranskanlukijalle poikkeukset ovat arkea. Jokaiseen kielioppisääntöön on poikkeus (tähänkin on poikkeus, joka siis on ei-poikkeus). En tiedä onko tällä mitään relevanssia todellisuuteen, mutta minusta tuskaa helpotti huomattavasti Système internationalin luoneen valtion kiroaminen. Kuka valtio se ikinä olikaan. Ei mitään hajua. Eikä kaunaa.

Vakavammin ottaen projektiin kuului totta kai myös taiteellisemman aivopuoliskon käyttöä. Olen kohtalaisen tyytyväinen siihen, että sivu ei näytä aivan 90-luvulta repäistyltä. Vielä tyytyväisempi olen siihen, että sivu on satoja kertoja Wolfram|Alphan etusivua pienempi, vaikka näyttääkin lievästi samanlaiselta!

Tähänkin työhön tarvittiin siis matematiikkaa, fysiikkaa, tietojenkäsittelyä ja ripaus graafista suunnittelua. Mitä seuraavaan projektiin tarvitaan, en tiedä. Siksi laaja-alaisuus kannattaa!

Ei kommentteja:

Lähetä kommentti

Kommentit ovat moderoituja — yritän hyväksyä kommenttisi mahdollisimman pian. Voit kirjoittaa kommenttiin LaTeX-koodia tai yksinkertaista HTML-merkintää: lue lisää Kommentointi-sivulta.