Tässä tehtävässä johdamme ylärajan modernin Eukleideen algoritmin ajan
kulutukselle.
Tärkein tavoitteemme ei kuitenkaan ole saada ylärajaa selville, vaan
harjoitella ohjelmista päättelemistä.
Voit käyttää vastauksissasi operaattoreita div ja
mod sekä kaksikantaista logaritmia log2.
MathCheck tuntee ne nykyisin.
SYT-algoritmi
Kertaamme aluksi hieman SYT-algoritmiin liittyviä asioita.
Jolleivät kertaamistehtävät ratkea tai jos jakoyhtälön käyttö ei tunnu
tutulta, kannattaa ensin suorittaa tehtävää Suurimman yhteisen tekijän algoritmi kohdan ”Aputuloksia”
loppuun saakka.
Oletamme, että `n` ja `m` ovat luonnollisia lukuja.
SYT-algoritmi voidaan esittää pseudokoodina seuraavasti:
1 while `m != 0` do
2 `k` := `n mod m`
3 `n` := `m`
4 `m` := `k`
Tässä on esimerkki SYT-algoritmin käyttäytymisestä:
`n`
`m`
laskutoimitus
49
70
`49 mod 70 = 49`
70
49
`70 mod 49 = 21`
49
21
`49 mod 21 = 7`
21
7
`21 mod 7 = 0`
7
0
lopetus
Rivien 2 ja 3 alussa `n`:llä ja `m`:llä on samat arvot kuin rivin 1 alussa.
Jos kierroksen alussa `n < m`
Siis silmukan kierros todellakin vaihtaa `n`:n ja `m`:n keskenään, jos sen
alussa `n < m`.
Jos kierroksen alussa `n = m`
Jos kierroksen alussa `n=m`, niin mitä SYT-algoritmi tekee?
VastausJos `n=m=0`, niin se lopettaa samantien.
Jos `n=m!=0`, niin se tekee yhden kierroksen ja lopettaa.
Kummassakin tapaukssa `n`:n arvo jää ennalleen.
Jos kierroksen alussa `n > m`
Esimerkissämme sen jälkeen kun `n` ja `m` oli saatu järjestykseen `n >
m`, ne pienenivät nopeasti.
Tämäkään ei ole sattumaa.
Todistamme seuraavaksi, että jos jonkin kierroksen alussa `n > m`, niin
kahta kierrosta myöhemmin `n` on pienentynyt alle puoleen (olettaen tietenkin,
että kierroksia on jäljellä ainakin kaksi).
Tämä saadaan todistamalla `M < n/2`, koska `n`:n arvo kahden kierroksen
jälkeen on sama kuin `m`:n arvo yhden kierroksen jälkeen eli `M`.
Jaamme tarkastelun kahteen osaan.
`M``=``M` on `m`:n arvolle rivin 4
lopussa annettu nimi.
Rivien 2 ja 4 ansiosta `m`:n arvo rivin 4 lopussa on
`n mod m`.`n mod m``<`Jakoyhtälön mukaan `0 <= I mod J < |J|`.
Nyt `I`:n paikalla on `n` ja `J`:n paikalla on `m`.`|m|``=`Luonnolliset luvut ovat 0, 1, 2, …, joten
ne kaikki ovat positiivisia tai nolla.
Siksi jokaiselle luonnolliselle luvulle `l` pätee `|l|=l`.
Kun aloitimme SYT-algoritmin käsittelyn, rajoitimme `n`:n ja `m`:n
luonnollisiin lukuihin.`m``<=`Sanoimme tämän pompulan alussa, että tässä pompulassa puhumme
vain niistä tilanteista, joissa `m <= n/2` pätee.
`n/2`.
Olemme osoittaneet, että jos `m <= n/2` pätee, niin tavoittelemamme asia
pätee, ja jos `m <= n/2` ei päde, niin tavoittelemamme asia pätee.
Niinpä tavoittelemamme asia pätee kaikissa tapauksissa, joissa kierroksen
alussa `n > m`.
(Olemme yhä otsikon ”Jos kierroksen alussa `n > m`” piirissä.)
Ylärajan käsite
Emme ole kiinnostuneet tämän pomppimisen yksityiskohdista.
Emme myöskään ole kiinnostuneet sellaisista tapauksista kuin `n=2000` ja
`m=1000`, joissa kierroksia tulee poikkeuksellisen vähän.
Haluamme helposti ymmärrettävän lausekkeen, josta saa käyttökelpoisen ylärajan
kierrosten määrälle, kun `n` ja `m` tunnetaan.
Sana ”yläraja” tarkoittaa, että todellinen lukuarvo on enintään se, mutta
voi olla vähemmänkin.
Hyvin paljon todellista lukuarvoa suurempi yläraja on yleensä helppo todistaa
päteväksi, mutta samasta syystä se ei anna hyödyllistä informaatiota.
Tehtävässä Suurimman yhteisen
tekijän algoritmi osoitettiin, että `m` pienenee jokaisella kierroksella.
Koska ohjelma lopettaa kun `m=0`, tästä seuraa, että kierroksia on korkeintaan
yhtä paljon kuin `m`:n arvo on alussa.
Siis `m` on pätevä yläraja kierrosten määrälle.
Se on kuitenkin isoilla `m` niin paljon todellista kierrosten määrää suurempi,
että se ei ole kovin hyödyllinen yläraja.
Esimerkiksi jos `m=1000000` se antaa ylärajaksi 1 000 000, vaikka tarkka arvo on
vain 25.
Johdamme ylärajan, joka on isoilla `n` ja `m` noin 44% suurempi kuin paras
mahdollinen sellainen yläraja, joka ei poukkoile ylös alas.
Näin tarkka yläraja antaa hyvän kuvan SYT-algoritmin suoritusajasta
huonoimmassa tapauksessa eli sellaisilla `n` ja `m`, jotka osuvat ylös alas
poukkoilun yläkohtiin.
Tätä tarkemman ylärajan johtaminen ei toisi paljoa lisäarvoa, mutta vaatisi
paljon enemmän matematiikkaa.
Yläraja kierrosten määrälle, jos alussa `n > m`
Lauseke antaa hullun tuloksen, jos `n=0`.
Mutta `n` ei voi olla 0, koska …olemme
yhä tapauksessa `n > m`, ja `m >= 0` koska se on luonnollinen
luku.
Yläraja yleisessä tapauksessa
Lauseke voitaisiin saada toimimaan myös kun `n=0` tekemällä siitä
monimutkaisempi.
Tietojenkäsittelytieteessä on kuitenkin tapana jättää se tekemättä, koska
kiinnostuksen kohteena on suoritusaika isoilla syötteillä.
Olemme selvittäneet ylärajan kierrosten määrälle `n`:n funktiona.
Entä jos haluammekin sen `m`:n funktiona?
…Ensimmäinen kierros kopioi `m`:n
arvon `n`:n paikalle ja sen jälkeen SYT-algoritmi jatkaa ikään kuin se arvo
olisi ollut alkuperäinen `n`:n arvo.
Lisäksi ensimmäinen kierros saattaa ehdon `n > m` voimaan.
Saadaan siis yksi plus tapauksen `n > m` yläraja siten, että `n`:n paikalla
on `m`.
Se on sama kuin yleisen tapauksen yläraja siten, että `n`:n paikalla on
`m`.
Koska SYT-algoritmi tekee kunkin kierroksen aikana vain perusoperaatioita
ja vain vakiomäärän, antaa kierrosten määrä oikean kuvan siitä, miten
suoritusaika kasvaa `n`:n (tai `m`:n) funktiona.
Kierrosten määrälle johtamamme yläraja ei ole paras mahdollinen, mutta silti
sen mukaan suoritusaika kasvaa hitaasti `n`:n funktiona.
Se riittää todistamaan, että SYT-algoritmi eli Eukleideen algoritmin moderni
versio on nopea.