Turvallinen asiointi verkkopankissa edellyttää tiedon salausta.
Yksi laskutoimitus, jota nykyaikaisissa salausmenetelmissä tarvitaan, on
an mod M, missä kaikki kolme lukua ovat isoja
(esimerkiksi 300-numeroisia).
Sen suorittaminen laskemalla n − 1 eli noin 10300
kertolaskua ja modulo-operaatiota veisi aikaa melko monta maailmankaikkeuden
ikää.
Tässä tehtävässä tutustutaan keinoon suorittaa lasku tarpeeksi nopeasti.
Yksinkertaisuuden vuoksi modulon ottaminen jätetään näyttämättä, mutta se on
helppo lisätä algoritmin joka kierrokselle.
Kerrataan aluksi pari asiaa.
Binääripotenssi näyttää tältä.
Harmaalla kirjoitettua riviä 4 ei oikeasti
tarvita, mutta sen lisääminen helpottaa algoritmista päättelemistä.
Sen lisääminen ei muuta sitä arvoa, mikä rivillä 6 sijoitetaan n:ään,
koska …rivin 3 ehdon vuoksi se
suoritetaan vain kun n on pariton, ja silloin n div 2 = Tämän näimme edellä.
(n − 1) / 2 = Kun jako menee
tasan, / tuottaa saman tuloksen kuin div.(n − 1) div 2.
(Miksi yhtäsuuruudet pätevät?)
Mitään muutakaan vaikutusta sen pois jättämisellä ei ole jatkoon, koska rivien
4 ja 6 välissä n:n arvoa ei käytetä mihinkään.
1 x := 1
2 whilen > 0 do
3 ifn mod 2 = 1
then
4 n :=
n − 1
5 x :=
x · a
6 n := n div 2
7 a := a · a
Algoritmi on kopioitu oikealle alas, jotta se olisi käsillä myös kun yllä
oleva kopio on kadonnut ruudun yläreunan yläpuolelle.
Merkitään muuttujien n ja a arvoja algoritmin alussa
symboleilla N ja A.
Algoritmin tehtävänä on siis laskea AN, missä
N on luonnollinen luku.
Todistamme, että algoritmi laskee oikean lopputuloksen ja selvitämme, kuinka
nopeasti se toimii.
Käytämme silmukoiden todistamisessa hyvin yleistä päättelytapaa, jossa on
viisi vaihetta:
Valitaan jokin väite, jolla päättely saadaan onnistumaan.
Sitä kutsutaan invariantiksi.
Binääripotenssin invariantti on yhtälö AN =
xan.
Osoitetaan, että invariantti pätee silmukan alussa eli kun riville 2
tullaan ensimmäisen kerran.
Osoitetaan, että silmukan vartalon suoritus ei voi saada invarianttia pois
voimasta (paitsi kenties tilapäisesti kesken vartalon suorituksen).
Siis osoitetaan, että jos AN =
xan pätee rivin 3 alussa ja silmukan ehto n
> 0 pätee, niin AN = xan
pätee rivin 7 lopussa.
Tästä, edellisestä ja siitä, että rivillä 2 ei muuteta minkään muuttujan arvoa
seuraa, että AN = xan on
voimassa aina rivin 2 alussa.
Osoitetaan, että jos invariantti pätee ja silmukan ehto ei päde, niin
silmukan lopputulokselta haluttu asia pätee, eli että algoritmi on laskenut
oikean lopputuloksen.
Koska potenssilasku ei ole määritelty esimerkiksi silloin kun kantaluku on
nolla ja eksponentti negatiivinen, meidän on pidettävä tarkkaan huolta, että
väitteissämme eksponentit ovat aina ei-negatiivisia.
Vastatessasi edelliseen kohtaan huomasit ehkä, että tämän muodon voi
päätellä suoraan, mutta voi olla vaikeaa miettiä pitääkö sijoituksen n
:= n − 1 vaikutus ottaa huomioon lisäämällä vai vähentämällä
invariantissa n:ään ykkönen.
Jos sijoituslauseen oikealla puolella on jotain monimutkaisempaa, vaikeus
kasvaa.
Siksi opettelemme kikan.
Ennen sijoituslausetta pätevä kaava kannattaa muuttaa muotoon, jossa
sijoituslauseen oikea puoli esiintyy sellaisenaan.
Tyypillisesti se esiintyy yhden kerran, mutta muutkin määrät ovat mahdollisia.
Sijoituksen kohteena oleva muuttuja ei saa esiintyä muualla kuin näissä
oikeissa puolissa.
Sijoituslauseen jälkeinen tilanne saadaan korvaamalla ne muuttujalla, johon
sijoitetaan.
Sijoituslauseen n := 2n + 1 ja kaavan 4n = k
tapauksessa se tarkoittaa, että ensin kaava muutetaan muotoon 2(2n + 1) − 2 = k.
Tämä on loogisesti yhtäpitävä alkuperäisen kaavan kanssa, koska
2(2n + 1) − 2 = 4n.
Sitten 2n + 1 korvataan n:llä, jolloin saadaan 2n − 2 =
k.
Tulokseksi saatiin, että jos ennen sijoitusta n := 2n + 1 päti
4n = k, niin sijoituksen jälkeen pätee 2n − 2 = k.
Olemme todistaneet, että jos invariantti on voimassa silmukan vartalon
alussa, se on voimassa myös silmukan vartalon lopussa.
Siis kohta 3 on valmis.
Koska kumpikin kahteen edelliseen laatikkoon kirjoittamistasi lausekkeista
on yhtäsuuri lausekkeen xan kanssa, ne ovat
yhtäsuuret myös keskenään, joten algoritmin tuottama vastaus on oikein.
Kohta 5 ja sitä myöten koko todistus on valmis.
Tämä algoritmi motivoitiin lupauksella nopeudesta, joten nyt on aika katsoa
kuinka nopea se on.
Algoritmin käyttämissä perusoperaatioissa ei ole mitään kertolaskua
monimutkaisempaa.
Kolmesataanumeroisten lukujen kertolasku ei ole yhtä pieni homma kuin
kymmennumeroisten, joten tarkassa laskelmassa kiinnitettäisiin huomiota
perusoperaatioiden hintaan.
Nyt emme kuitenkaan ole niin tarkkoja, vaan katsomme ainoastaan silmukan
kierrosten määrää.
Kolmesataanumeroisilla luvuilla tulee siis hiukan alle tuhat kierrosta.
Tietokoneelle se on kohtuullinen työmäärä siitäkin huolimatta, että
peruslaskutoimitukset tehdään 300-numeroisilla luvuilla.