Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa - johdanto - matemaattinen induktiotodistus - matriisien kertolaskun käyttömahdollisuus - käsinlaskuesimerkkejä - kaikki välivaiheet esittävä ohjelma Mathematicalla Laajennettu Eukleideen algoritmi - suoraviivainen tapa Etsitään annettujen positiivisten lukujen a ja b suurimman yhteisen tekijän d = syt(a, b) esitys lukujen a ja b lineaarkombinaationa muodossa d = u a + v b; u, v Z; suoraviivaisella tavalla. Tässä tavassa jakoalgoritmin tuottama jakojäännös r i esitetään jokaisella askeleella muodossa u i a + v i b. Viimeisen jakojäännöksen r n ollessa nolla, on viimeinen nollasta eroava jakojäännös r n-1 etsitty lineaarikombinaatio d = syt(a, b) = r n-1 = u a + v b. Aloitetaan laskemalla yksityiskohtaisesti useita ensimmäisiä rivejä: a b > 0 a = q 1 b + r 1 ; r 1 = a q 1 b = u 1 a + v 1 b, missä u 1 = 1, v 1 = q 1 Z b = q 2 r 1 + r 2 ; r 2 = b q 2 r 1 = b q 2 (a q 1 b) = q 2 a + (1 q 2 v 1 )b = u 2 a + v 2 b, missä u 2 = q 2, v 2 = 1 q 2 v 1 r 1 = q 3 r 2 + r 3 ; r 3 = r 1 q 3 r 2 = (a q 1 b ) q 3 (b q 2 (a q 1 b )) = u 1 a + v 1 b q 3 (q 2 a + (1 q 2 v 1 )b) = u 1 a + v 1 b q 3 ( u 2 a + v 2 b) = (u 1 q 3 u 2 )a + (v 1 q 3 v 2 )b = u 3 a + v 3 b, missä u 3 = u 1 q 3 u 2, v 3 = v 1 q 3 v 2 r 2 = q 4 r 3 + r 4 ; r 4 = r 2 q 4 r 3 = (b q 2 (a q 1 b )) q 4 ((a q 1 b ) q 3 (b q 2 (a q 1 b ))) = u 2 a + v 2 b q 4 (u 3 a + v 3 b) = (u 2 q 4 u 3 )a + (v 2 q 4 v 3 )b = u 4 a + v 4 b, missä u 4 = u 2 q 4 u 3, v 4 = v 2 q 4 v 3 r 3 = q 5 r 4 + r 5 ; r 5 = r 3 q 5 r 4 = u 5 a + v 5 b, missä u 5 = u 3 q 5 u 4, v 5 = v 3 q 5 v 4 ja niin edelleen. Meillä on siis a = q 1 b + r 1, r 1 = a q 1 b b = q 2 r 1 + r 2, r 2 = b q 2 r 1. Tämän lisäksi yleiset jakojäännökset sekä kertoimet u i ja v i ovat ilmeisestikin muotoa r i = r i-2 q i r i-1 = u i a + v i b,
Salakirjoitus 2 missä u i = u i-2 q i u i-1 ja v i = v i-2 q i v i-1, aina kun i 3. (*) Koska u 1 = 1, v 1 = q 1 ja u 2 = q 2, v 2 = 1 q 2 v 1, niin u 2 = u 0 q 2 u 1, v 2 = v 0 q 2 v 1, kun u 0 = 0 ja v 0 = 1. Toisin sanoen, valitsemalla r 0 = b; u 0 = 0 ja v 0 = 1 sekä u 1 = 1, v 1 = q 1, voidaan (*) laajentaa koskemaan myös arvoa i = 2. Saadaan siis r 1 = a q 1 b r i = r i-2 q i r i-1 = u i a + v i b u i = u i-2 q i u i-1 v i = v i-2 q i v i-1, aina kun i 2. Merkitään vielä r -1 = a, r 0 = b; u -1 = 1 ja v -1 = 0 sekä u 0 = 0 ja v 0 = 1. Tällöin ensimmäinen yhtäsuuruus r 1 = a q 1 b sekä arvot u 1 ja v 1 saadaan yleisistä palautuskaavoista myös tapauksessa i = 1: r i = r i-2 q i r i-1 = u i a + v i b u i = u i-2 q i u i-1 v i = v i-2 q i v i-1, aina kun i 1. Yllä esitetyistä laskelmista voidaan myös havaita, että luvun a (> 0) kerroin u i on positiivinen aina kun indeksi i on pariton ja negatiivinen aina kun i > 0 on parillinen. Luvun b (> 0) kertoimen v i etumerkki puolestaan vaihtelee päinvastoin: v i on negatiivinen aina kun indeksi i > 0 on pariton ja positiivinen aina kun i on parillinen. Esitetään seuraavaksi tämä laajennettu Eukleideen algoritmi valmiin ohjelman muodossa (kuten jo kappaleessa 2.2), ja todistetaan sen virheetön toiminta matemaattisella induktiolla. Algoritmi 2.2 Laajennettu Eukleideen algoritmi syöte a b > 0 alkuarvot r -1 = a; r 0 = b; u -1 = 1; u 0 = 0; v -1 = 0; v 0 = 1; n = 0; while r n > 0 do begin aseta n = n + 1; tulosta r n-2 = q n r n-1 + r n, r n-1 > r n 0; aseta u n = u n-2 - q n u n-1 ; aseta v n = v n-2 - q n v n-1 ; end aseta u = u n-1 ; v = v n-1 ; (2.2) syt(a, b) = r n-1 = u a + v b Algoritmin 2.2 oikeellisuuden todistus: Aluksi huomataan, että luvut r n, n 1, muodostavat ei-negatiivisten kokonaislukujen aidosti vähenevän jonon. Näin ollen algoritmin toiminta päättyy vähintään a iteraation jälkeen (käytännössä huomattavan paljon nopeammin).
Salakirjoitus 3 Algoritmin palauskaavasta r i = r i-2 q i r i-1 seuraa, että jokainen jakojäännöksien r i-2 ja r i-1 yhteinen tekijä on myös jakojäännöksien r i ja r i-1 yhteinen tekijä. Toisaalta jokainen jakojäännöksien r i ja r i-1 tekijä t on myös lukujen r i-2 ja r i-1 tekijä, koska muodoista r i = t r i ' ja r i-1 = t r i-1 ' (t, r i ', r i-1 ' Z + ) seuraa palautuskaavan nojalla, että r i-2 = r i + q i r i-1 = t r i ' + q i t r i-1 ' = t (r i ' + q i r i-1 '), ts. t on luvun r i-2 (ja oletuksen mukaan myös luvun r i-1 ) tekijä. Siis syt(r i-2, r i-1 ) = syt(r i-1, r i ), aina kun 1 i n, ja näin ollen syt(a, b) = syt(r -1, r 0 ) = syt(r 0, r 1 ) = syt(r 1, r 2 ) = = syt(r n-1, r n ) = syt(r n-1, 0) = r n-1. Tämä todistaa ensimmäisen yhtäsuuruuden kohdassa (2.2). Osoitamme nyt, että kaikille k, -1 k n, on voimassa (2.3) u k a + v k b = r k. Huomaa, että tässä sijoitus k = n - 1 tuottaa toisen yhtäsuuruuden kohdassa (2.2). Kun k = -1 ja k = 0 relaatio (2.2) on voimassa alkuarvojen r -1 = a; r 0 = b; u -1 = 1; u 0 = 0; v -1 = 0; v 0 = 1; valinnan perusteella. Jatketaan matemaattisella induktiolla. Tehdään induktio-oletus (i.o.), että (2.2) on voimassa, kun n = k 2 ja kun n = k 1. Algoritmin palautuskaavojen ja induktio-oletuksen nojalla seuraa, että r k = r k-2 - q k r i.o. k-1 = {u k-2 a + v k-2 b} - q k {u k-1 a + v k-1 b} = (u k-2 q k u k-1 ) a + (v k-2 q k v k-1 ) b = u k a + v k b. Induktioperiaatteen nojalla kohta (2.3) on tosi. Näin ollen Algoritmi 2.2 toimii oikein. Tietenkään ei ole välttämätöntä tallettaa kaikkia muuttujien r k, u k ja v k väliarvoja. Vain kaksi viimeistä yhdessä q k :n kanssa riittää. Muut väliarvot olivat mukana algoritmissa vain helpottamassa todistuksen lukemista. Huomautus. Koska kertoimet u i ja v i lasketaan lineaaristen yhtälöiden u i = u i-2 q i u i-1 v i = v i-2 q i v i-1 avulla, voitaisiin ne ja saman tien seuraavalla askeleella tarvittavat u i-1 ja v i-1 tuottaa ja tallentaa matriisimuodossa seuraavasti: u i v i u i-1 v i-1 = -q i 1 1 0 u i-1 v i-1 u i-2 v i-2. Koska u -1 = 1; u 0 = 0; v -1 = 0; v 0 = 1; meillä on u 0 v 0 u -1 v -1 = 0 1 1 0. Kun i = 1, saadaan u 1 v 1 u 0 v 0 = -q 1 1 1 0 0 1 1 0. Seuravassa askeleessa saadaan u 2 v 2 u 1 v 1 = -q 2 1 1 0 u 1 v 1 u 0 v 0 = -q 2 1 1 0 ( -q 1 1 1 0 0 1 1 0 ). Tässä kahden viimeisen matriisin ympärillä olevat sulkumerkit voidaan jättää merkitsemättä matriisien liitäntä- eli
Salakirjoitus 4 assosiatiivisuusominaisuuksien nojalla. Lopullisessa lineaarikombinaatiossa syt(a, b) = r n-1 = u a + v b kertoimet ovat u = u n-1 ; v = v n-1 ja ne löytyvät n 1 matriisikertolaskun jälkeen saatavan tulomatriisin ensimmäiseltä vaakariviltä sen jälkeen, kun tarvittavat kertoimet q i ovat löytyneet: u n-1 v n-1 u n-2 v n-2 = -q n-1 1 1 0 -q 2 1 1 0 -q 1 1 1 0 0 1 1 0. Alla olevassa käsinlaskuesimerkissä, jossa lasketaan syt(368, 123), saadaan q 1 = 2 ja q 2 = 1. Tuossa tapauksessa on kolme riviä, joten n = 3. Kertoimiksi saadaan u = u n-1 = -1 ; v = v n-1 = 3. Nämä luvut löytyvät tulomatriisin ensimmäiseltä vaakariviltä: -1 1-2 1. 1 0 1 0. 0 1 1 0-1 3 1-2 Jätämme lukijalle tämän elegantin laskentatavan ohjelmoinnin harjoitustehtäväksi emmekä enää käsittele sitä tässä yhteydessä. Käsinlaskuesimerkki: a = 368 ja b = 123 Tässä syt = 1, mikä nähdään Eukleideen algoritmilla seuraavasti: 368 = 2 * 123 + 122 123 = 1 * 122 + 1 122 = 122 * 1 + 0 Viimeinen nollasta eroava jakojäännös = 1 = syt(368, 123). Esitetään syt = 1 nyt lukujen a = 368 ja b = 123 lineaarikombinaationa. Tässä yksinkertaisessa tilanteessa laskelmat on helppo tehdä käsin. Meillä siis on voimassa r i = r i-2 q i r i-1 = u i a + v i b, missä u i = u i-2 q i u i-1, v i = v i-2 q i v i-1, u 0 = 0 ja v 0 = 1 sekä u 1 = 1, v 1 = q 1. Niinpä laskemme seuraavasti: r i-2 = q i r i-1 + r i ; r i = r i-2 q i r i-1 = u i a + v i b ; u i, v i, q i ----------------------- ----------------------------------- ----------- 368 = 2*123 + 122 ; 122 = 368 2*123 ; u 1 = 1, v 1 = q 1 = 2 123 = 1*122 + 1 ; 1 = 123 1*(368 2*123) = 1* 368 + 3*123 ; u 2 = u 0 q 2 u 1 = 0 1*1 = 1, v 2 = v 0 q 2 v 1 = 1 1*( 2) = 3
Salakirjoitus 5 122 = 122*1 + 0 ; 1 = syt(368, 123) = u a + v b, missä u = u 2 = 1 ja v = v 2 = 3. Siis syt(368, 123) = 1 = 1* 368 + 3*123. Tämä tulos on helppo varmistaa ja todeta oikeaksi. Käsinlaskuesimerkki: a = 1431 ja b = 1368 Tässä syt = 9, mikä nähdään Eukleideen algoritmilla seuraavasti: 1431 = 1 * 1368 + 63 1368 = 21 * 63 + 45 63 = 1 * 45 + 18 45 = 2 * 18 + 9 18 = 2 * 9 + 0 Viimeinen nollasta eroava jakojäännös = 9 = syt(1431, 1368). Laketaan vielä lineaarikombinaatio 9 = u i a + v i b. Tässä a = 1431 ja b = 1368 sekä kuten edellä r i = r i-2 q i r i-1 = u i a + v i b, missä u i = u i-2 q i u i-1, v i = v i-2 q i v i-1, u 0 = 0 ja v 0 = 1 sekä u 1 = 1, v 1 = q 1. Keskitytään nyt vain kaikkein oleellisiimpaan, eli lukujen u i ja v i laskemiseen kullakin askeleella: r i-2 = q i r i-1 + r i ; r i = r i-2 q i r i-1 = u i a + v i b ; u i, v i, q i ----------------------- ----------------------------------- ----------- 1431 = 1*1368 + 63 63 = a b = u 1 a + v 1 b; u 1 = 1, v 1 = q 1 = 1 1368 = 21*63 + 45 45 = u 2 a + v 2 b; u 2 = u 0 q 2 u 1 = 0 21*1 = 21, v 2 = v 0 q 2 v 1 = 1 21*( 1) = 22 63 = 1*45 + 18 18 = u 3 a + v 3 b; u 3 = u 1 q 3 u 2 = 1 1*( 21) = 22, v 3 = v 1 q 3 v 2 = 1 1*22 = 23 45 = 2*18 + 9 9 = u 4 a + v 4 b; u 4 = u 2 q 4 u 3 = 21 2*22 = 65, v 4 = v 2 q 4 v 3 = 22 2*( 23) = 68 18 = 2*9 + 0 9 = syt(1431, 1368) = u a + v b, missä u = u 4 = 65 ja v = v 4 = 68. Siis syt(1431, 1368) = 9 = 65*1431 + 68*1368. Tarkista vielä tämä tulos kertomalla luvut ja laskemalla saadut tulot yhteen. Laajennetun Eukleideen algoritmin ohjelmointi Mathematicalla Esitetään aluksi Eukleideen perusalgoritmi ilman lineaarikombinaatiota. Tällöin laskelmien rakenne on varsin yksinkertainen. Jos käyttäjän antama (positiivinen luku) a on pienempi kuin b, vaihdetaan ensin näiden lukujen a ja b järjestys:
Salakirjoitus 6 Clear[f]; f[{a_, b_}] := If[a b, {a, "=", Floor[a / b], "*", b, "+", a - Floor[a / b] * b}, f[{b, a}]]; f[{a_, _, _, _, b_, _, r_}] := Module[{myPr = ""}, If[r 0, Print["\nTässä syt = ", b, ".", "\n\ntulos nähdään Eukleideen algoritmilla seuraavasti:\n"]; mypr, {b, "=", Floor[b / r], "*", r, "+", b - Floor[b / r] * r}]]; Esimerkki: Clear[Eukleides]; Eukleides[a_, b_] := ( Print[ (steps = Rest[NestWhileList[f, {a, b}, (# =!= "") &]]) // TableForm]; Print["Viimeinen nollasta eroava jakojäännös = ", Last[steps[[Length[steps] - 2]]], " = syt(", a, ", ", b, ")."] ) Eukleides[1234, 2345] Tässä syt = 1. Tulos nähdään Eukleideen algoritmilla seuraavasti: 2345 = 1 * 1234 + 1111 1234 = 1 * 1111 + 123 1111 = 9 * 123 + 4 123 = 30 * 4 + 3 4 = 1 * 3 + 1 3 = 3 * 1 + 0 Viimeinen nollasta eroava jakojäännös = 1 = syt(1234, 2345). Palautetaan seuraavaksi mieleen yllä todistetun laajennetun algoritmin pseudokoodi: Algoritmi 2.2 Laajennettu Eukleideen algoritmi syöte a b > 0
Salakirjoitus 7 alkuarvot r -1 = a; r 0 = b; u -1 = 1; u 0 = 0; v -1 = 0; v 0 = 1; n = 0; while r n > 0 do begin aseta n = n + 1; tulosta r n-2 = q n r n-1 + r n, r n-1 > r n 0; aseta u n = u n-2 - q n u n-1 ; aseta v n = v n-2 - q n v n-1 ; end aseta u = u n-1 ; v = v n-1 ; Meillä on siis aluksi: r -1 = a; r 0 = b; (a b > 0) u -1 = 1; u 0 = 0; v -1 = 0; v 0 = 1; n = 0; r -1 = a = q 1 b + r 1 ; r 1 = a q 1 b = u 1 a + v 1 b, missä u 1 = u -1 q 1 u 0, v 1 = v -1 q 1 v 0 r 0 = b = q 2 r 1 + r 2 ; r 2 = b q 2 r 1 = u 2 a + v 2 b, missä u 2 = u 0 q 2 u 1, v 2 = v 0 q 2 v 1 r 1 = q 3 r 2 + r 3 ; r 3 = u 3 a + v 3 b, missä u 3 = u 1 q 3 u 2, v 3 = v 1 q 3 v 2 r 2 = q 4 r 3 + r 4 ; r 4 = u 4 a + v 4 b, missä u 4 = u 2 q 4 u 3, v 4 = v 2 q 4 v 3 Esitetään nyt jakoalgoritmin suorittava funktio jako ja sitä käyttävä funktio laajennettueukleides: Clear[jako]; jako[{a_, b_}] := If[a b, Print[r -1, "=", a, "=", q 1, "*", r 0, "+", r 1, "=", Floor[a / b], "*", b, "+", a - Floor[a / b] * b, "; ", r 1, "=", a - Floor[a / b] * b, "=", u 1, "a +", v 1, "b", " = ", "(", 1-0, ")*", a, " + (", 0 - Floor[a / b], ")*", b]; {1, a, Floor[a / b], b, a - Floor[a / b] * b, {0, 1}, 1-0, a, 0 - Floor[a / b], b} (* = {indeksi=n=1,r -1,q 1, r 0,r 1,{u 0,v 0 },u 1 =u -1 -q 1 *u 0,a,v 1 =v -1 -q 1 *v 0,b} *), jako[{b, a}]]; jako[ {n_, r1_, q3_, r2_, r3_, {u2_, v2_}, u3_, a_, v3_, b_}] := Module[{i, q4, r4, u4, v4, nextstep}, If[r3 0, "", (q4 = Floor[r2 / r3]; r4 = r2 - q4 * r3; u4 = u2 - q4 * u3; v4 = v2 - q4 * v3; nextstep = {i = n + 1, r2, q4, r3, r4, {u3, v3}, u4, a, v4, b}; Print[r i-2, "=", r2, "=", q i, "*", r i-1, "+", r i, "=", q4, "*", r3, "+", r4, "; ", r i, "=", r4, "=", u i, "a +", v i, "b", " = ", "(", u4, ")*", a, " + (", v4, ")*", b]; nextstep)]];
Salakirjoitus 8 Clear[laajennettuEukleides]; laajennettueukleides[a_, b_] := (Print["Laajennettu Eukleideen algoritmi toimii seuraavasti:"]; Print["a = ", Max[a, b], ", b = ", Min[a, b]]; lastrelevantstep = NestWhile[jako, {a, b}, (# =!= "") &, 1, Infinity, -2]; Print["Viimeinen nollasta eroava jakojäännös = ", lastrelevantstep[[5]], " = syt(", a, ", ", b, ")."]; Print["Lineaarikombinaatio: ", lastrelevantstep[[5]], " = u a + v b = ", "(", lastrelevantstep[[7]], ")*", Max[a, b], " + (", lastrelevantstep[[9]], ")*", Min[a, b], "."];); Esimerkki: laajennettueukleides[123,368] laajennettueukleides[123, 368] Laajennettu Eukleideen algoritmi toimii seuraavasti: a = 368, b = 123 r -1 =368=q 1 *r 0 +r 1 =2*123+122; r 1 =122=u 1 a +v 1 b = (1)*368 + (-2)*123 r 0 =123=q 2 *r 1 +r 2 =1*122+1; r 2 =1=u 2 a +v 2 b = (-1)*368 + (3)*123 r 1 =122=q 3 *r 2 +r 3 =122*1+0; r 3 =0=u 3 a +v 3 b = (123)*368 + (-368)*123 Viimeinen nollasta eroava jakojäännös = 1 = syt(123, 368). Lineaarikombinaatio: 1 = u a + v b = (-1)*368 + (3)*123. Tarkistuslaskelmia luvuilla a ja b sekä tuloksena saaduilla luvuilla u ja v: lastrelevantstep (* siis {i,r i-2,q i,r i-1,r i,{u i-1,v i-1 },u i,a,v i,b}, kun i = n-1 *) {2, 123, 1, 122, 1, {1, -2}, -1, 368, 3, 123}
Salakirjoitus 9 Print["Lineaarikombinaatio u a + v b = ", "(", lastrelevantstep[[-4]], ")*", lastrelevantstep[[-3]], " + (", lastrelevantstep[[-2]], ")*", lastrelevantstep[[- 1]], " tuottaa sievennettynä luvun:"]; lastrelevantstep[[- 4]] * lastrelevantstep[[- 3]] + lastrelevantstep[[-2]] * lastrelevantstep[[-1]] Lineaarikombinaatio u a + v b = (-1)*368 + (3)*123 tuottaa sievennettynä luvun: 1 Tämähän on aivan oikein. Esimerkki: laajennettueukleides[34527,18273645] laajennettueukleides[34 527, 18 273 645] Laajennettu Eukleideen algoritmi toimii seuraavasti: a = 18 273 645, b = 34 527 r -1 =18 273 645=q 1 *r 0 +r 1 =529*34 527+8862 ; r 1 =8862=u 1 a +v 1 b = (1)*18 273 645 + (-529)*34 527 r 0 =34 527=q 2 *r 1 +r 2 =3*8862+7941; r 2 = 7941=u 2 a +v 2 b = (-3)*18 273 645 + (1588)*34 527 r 1 =8862=q 3 *r 2 +r 3 =1*7941+921; r 3 = 921=u 3 a +v 3 b = (4)*18 273 645 + (-2117)*34 527 r 2 =7941=q 4 *r 3 +r 4 =8*921+573; r 4 = 573=u 4 a +v 4 b = (-35)*18 273 645 + (18 524)*34 527 r 3 =921=q 5 *r 4 +r 5 =1*573+348; r 5 =348 =u 5 a +v 5 b = (39)*18 273 645 + (-20 641)*34 527 r 4 =573=q 6 *r 5 +r 6 =1*348+225; r 6 =225 =u 6 a +v 6 b = (-74)*18 273 645 + (39 165)*34 527
Salakirjoitus 10 r 5 =348=q 7 *r 6 +r 7 =1*225+123; r 7 =123 =u 7 a +v 7 b = (113)*18 273 645 + (-59 806)*34 527 r 6 =225=q 8 *r 7 +r 8 =1*123+102; r 8 =102 =u 8 a +v 8 b = (-187)*18 273 645 + (98 971)*34 527 r 7 =123=q 9 *r 8 +r 9 =1*102+21; r 9 =21 =u 9 a +v 9 b = (300)*18 273 645 + (-158 777)*34 527 r 8 =102=q 10 *r 9 +r 10 =4*21+18; r 10 =18= u 10 a +v 10 b = (-1387)*18 273 645 + (734 079)*34 527 r 9 =21=q 11 *r 10 +r 11 =1*18+3; r 11 =3= u 11 a +v 11 b = (1687)*18 273 645 + (-892 856)*34 527 r 10 =18=q 12 *r 11 +r 12 =6*3+0; r 12 =0=u 12 a +v 12 b = (-11 509)*18 273 645 + (6 091 215)*34 527 Viimeinen nollasta eroava jakojäännös = 3 = syt(34 527, 18 273 645). Lineaarikombinaatio: 3 = u a + v b = (1687)*18 273 645 + (-892 856)*34 527. Tarkistuslaskelmia luvuilla a ja b sekä tuloksena saaduilla luvuilla u ja v: lastrelevantstep (* siis {i,r i-2,q i,r i-1,r i,{u i-1,v i-1 },u i,a,v i,b}, kun i = n-1 *) {11, 21, 1, 18, 3, {-1387, 734 079}, 1687, 18 273 645, -892 856, 34 527}
Salakirjoitus 11 Print["Lineaarikombinaatio u a + v b = ", "(", lastrelevantstep[[-4]], ")*", lastrelevantstep[[-3]], " + (", lastrelevantstep[[-2]], ")*", lastrelevantstep[[- 1]], " tuottaa sievennettynä luvun:"]; lastrelevantstep[[- 4]] * lastrelevantstep[[- 3]] + lastrelevantstep[[-2]] * lastrelevantstep[[-1]] Lineaarikombinaatio u a + v b = (1687)*18 273 645 + (-892 856)*34 527 tuottaa sievennettynä luvun: 3 Tämäkin on oikein. Kokeillaan saadun syt(a,b) :n laskemista vielä Eukleideen perusalgoritmilla ilman lineaarikombinaatiota. Tällöin laskelmien rakenne on yksinkertainen. Samat laskelmat ovat toki näkyvissä jo edellisen tulostuksen vasemmanpuoleisessa reunassa. Eukleides[34 527, 18 273 645] Tässä syt = 3. Tulos nähdään Eukleideen algoritmilla seuraavasti: 18 273 645 = 529 * 34 527 + 8862 34 527 = 3 * 8862 + 7941 8862 = 1 * 7941 + 921 7941 = 8 * 921 + 573 921 = 1 * 573 + 348 573 = 1 * 348 + 225 348 = 1 * 225 + 123 225 = 1 * 123 + 102 123 = 1 * 102 + 21 102 = 4 * 21 + 18 21 = 1 * 18 + 3 18 = 6 * 3 + 0 Viimeinen nollasta eroava jakojäännös = 3 = syt(34 527, 18 273 645).
Salakirjoitus 12 Esimerkki: a = Fibonacci[100]; b = Fibonacci[99]; laajennettueukleides[354224848179261915075, 218922995834555169026] a = Fibonacci[100] b = Fibonacci[99] 354 224 848 179 261 915 075 218 922 995 834 555 169 026 laajennettueukleides[a, b] Laajennettu Eukleideen algoritmi toimii seuraavasti: a = 354 224 848 179 261 915 075, b = 218 922 995 834 555 169 026 r -1 =354 224 848 179 261 915 075 =q 1 *r 0 +r 1 =1*218 922 995 834 555 169 026 +135 301 852 344 706 746 049 ; r 1 =135 301 852 344 706 746 049 =u 1 a +v 1 b = (1)*354 224 848 179 261 915 075 + (-1)*218 922 995 834 555 169 026 r 0 =218 922 995 834 555 169 026 =q 2 *r 1 +r 2 =1*135 301 852 344 706 746 049 +83 621 143 489 848 422 977 ; r 2 =83 621 143 489 848 422 977 =u 2 a +v 2 b = (-1)*354 224 848 179 261 915 075 + (2)*218 922 995 834 555 169 026 r 1 =135 301 852 344 706 746 049 =q 3 *r 2 +r 3 =1*83 621 143 489 848 422 977 +51 680 708 854 858 323 072 ; r 3 =51 680 708 854 858 323 072 =u 3 a +v 3 b = (2)*354 224 848 179 261 915 075 + (-3)*218 922 995 834 555 169 026 Tähän väliin jäävät ohjelman tulostukset on tarkoituksella poistettu. r 94 =5=q 96 *r 95 +r 96 =1*3+2; r 96 =2=u 96 a +v 96 b = (-51 680 708 854 858 323 072 )* 354 224 848 179 261 915 075 + (83 621 143 489 848 422 977 )*218 922 995 834 555 169 026 r 95 =3=q 97 *r 96 +r 97 =1*2+1; r 97 =1=u 97 a +v 97 b = (83 621 143 489 848 422 977 )* 354 224 848 179 261 915 075 + (-135 301 852 344 706 746 049 )*218 922 995 834 555 169 026 r 96 =2=q 98 *r 97 +r 98 =2*1+0; r 98 =0=u 98 a +v 98 b = (-218 922 995 834 555 169 026 )* 354 224 848 179 261 915 075 + (354 224 848 179 261 915 075 )*218 922 995 834 555 169 026 Viimeinen nollasta eroava jakojäännös = 1 = syt( 354 224 848 179 261 915 075, 218 922 995 834 555 169 026 ). Lineaarikombinaatio: 1 = u a + v b = (83 621 143 489 848 422 977 )* 354 224 848 179 261 915 075 + (-135 301 852 344 706 746 049 )*218 922 995 834 555 169 026.
Salakirjoitus 13 Tarkistuslaskelmia luvuilla a ja b sekä tuloksena saaduilla luvuilla u ja v: lastrelevantstep (* siis {i,r i-2,q i,r i-1,r i,{u i-1,v i-1 },u i,a,v i,b}, kun i = n-1 *) {97, 3, 1, 2, 1, {-51 680 708 854 858 323 072, 83 621 143 489 848 422 977}, 83 621 143 489 848 422 977, 354 224 848 179 261 915 075, -135 301 852 344 706 746 049, 218 922 995 834 555 169 026} Print["Lineaarikombinaatio u a + v b = ", "(", lastrelevantstep[[-4]], ")*", lastrelevantstep[[-3]], " + (", lastrelevantstep[[-2]], ")*", lastrelevantstep[[- 1]], " tuottaa sievennettynä luvun:"]; lastrelevantstep[[- 4]] * lastrelevantstep[[- 3]] + lastrelevantstep[[-2]] * lastrelevantstep[[-1]] Lineaarikombinaatio u a + v b = (83 621 143 489 848 422 977 )*354 224 848 179 261 915 075 + (-135 301 852 344 706 746 049 )*218 922 995 834 555 169 026 tuottaa sievennettynä luvun: 1 Tulos on oikein! Näille suurille luvuille Fibonacci[100] ja Fibonacci[99] tarvittiin suurimman yhteisen tekijän laskemiseen vain 97 + 1 = 98 askelta, vaikka kyseessä on hankalin mahdollinen tapaus (kun algoritmin toiminnan nopeutta verrataan luvun b arvoon, a > b 1). Todellakin, algoritmin toiminta on hitaimmillaan silloin, kun jakojäännös r k pienenee kussakin askeleessa r k-2 = q k r k-1 + r k mahdollisimman vähän. Tällaiseen tilanteeseen puolestaan joudutaan, jos r k-2 = r k-1 + r k aina kun 2 k n - 1, ts. jos jokaisella askeleella osamäärä q k saa arvon 1 (mahdollisesti ensimmäistä askelta a = q 1 b + r 1 lukuunottamatta). Tarkemmin tätä asiaa käsitellään päätekstin Kappaleessa 2.3. Se että kaikki kertoimet q i ovat ykkösiä tapauksessa a = Fibonacci[100], b = Fibonacci[99] näkyy helpoiten perusalgoritmista: Eukleides[ a = Fibonacci[100], b = Fibonacci[99] ] Tässä syt = 1. Tulos nähdään Eukleideen algoritmilla seuraavasti: 354 224 848 179 261 915 075 = 1 * 218 922 995 834 555 169 026 + 135 301 852 344 218 922 995 834 555 169 026 = 1 * 135 301 852 344 706 746 049 + 83 621 143 489
Salakirjoitus 14 135 301 852 344 706 746 049 = 1 * 83 621 143 489 848 422 977 + 51 680 708 854 83 621 143 489 848 422 977 = 1 * 51 680 708 854 858 323 072 + 31 940 434 634 51 680 708 854 858 323 072 = 1 * 31 940 434 634 990 099 905 + 19 740 274 219 31 940 434 634 990 099 905 = 1 * 19 740 274 219 868 223 167 + 12 200 160 415 19 740 274 219 868 223 167 = 1 * 12 200 160 415 121 876 738 + 7 540 113 804 74 12 200 160 415 121 876 738 = 1 * 7 540 113 804 746 346 429 + 4 660 046 610 37 7 540 113 804 746 346 429 = 1 * 4 660 046 610 375 530 309 + 2 880 067 194 37 4 660 046 610 375 530 309 = 1 * 2 880 067 194 370 816 120 + 1 779 979 416 00 2 880 067 194 370 816 120 = 1 * 1 779 979 416 004 714 189 + 1 100 087 778 36 1 779 979 416 004 714 189 = 1 * 1 100 087 778 366 101 931 + 679 891 637 638 1 100 087 778 366 101 931 = 1 * 679 891 637 638 612 258 + 420 196 140 727 679 891 637 638 612 258 = 1 * 420 196 140 727 489 673 + 259 695 496 911 420 196 140 727 489 673 = 1 * 259 695 496 911 122 585 + 160 500 643 816 259 695 496 911 122 585 = 1 * 160 500 643 816 367 088 + 99 194 853 094 160 500 643 816 367 088 = 1 * 99 194 853 094 755 497 + 61 305 790 721 99 194 853 094 755 497 = 1 * 61 305 790 721 611 591 + 37 889 062 373 61 305 790 721 611 591 = 1 * 37 889 062 373 143 906 + 23 416 728 348 37 889 062 373 143 906 = 1 * 23 416 728 348 467 685 + 14 472 334 024 23 416 728 348 467 685 = 1 * 14 472 334 024 676 221 + 8 944 394 323 79 14 472 334 024 676 221 = 1 * 8 944 394 323 791 464 + 5 527 939 700 88 8 944 394 323 791 464 = 1 * 5 527 939 700 884 757 + 3 416 454 622 90 5 527 939 700 884 757 = 1 * 3 416 454 622 906 707 + 2 111 485 077 97 3 416 454 622 906 707 = 1 * 2 111 485 077 978 050 + 1 304 969 544 92 2 111 485 077 978 050 = 1 * 1 304 969 544 928 657 + 806 515 533 049 1 304 969 544 928 657 = 1 * 806 515 533 049 393 + 498 454 011 879 806 515 533 049 393 = 1 * 498 454 011 879 264 + 308 061 521 170 498 454 011 879 264 = 1 * 308 061 521 170 129 + 190 392 490 709 308 061 521 170 129 = 1 * 190 392 490 709 135 + 117 669 030 460 190 392 490 709 135 = 1 * 117 669 030 460 994 + 72 723 460 248 117 669 030 460 994 = 1 * 72 723 460 248 141 + 44 945 570 212 72 723 460 248 141 = 1 * 44 945 570 212 853 + 27 777 890 035 44 945 570 212 853 = 1 * 27 777 890 035 288 + 17 167 680 177 27 777 890 035 288 = 1 * 17 167 680 177 565 + 10 610 209 857 17 167 680 177 565 = 1 * 10 610 209 857 723 + 6 557 470 319 84 10 610 209 857 723 = 1 * 6 557 470 319 842 + 4 052 739 537 88 6 557 470 319 842 = 1 * 4 052 739 537 881 + 2 504 730 781 96 4 052 739 537 881 = 1 * 2 504 730 781 961 + 1 548 008 755 92 2 504 730 781 961 = 1 * 1 548 008 755 920 + 956 722 026 041 1 548 008 755 920 = 1 * 956 722 026 041 + 591 286 729 879 956 722 026 041 = 1 * 591 286 729 879 + 365 435 296 162 591 286 729 879 = 1 * 365 435 296 162 + 225 851 433 717 365 435 296 162 = 1 * 225 851 433 717 + 139 583 862 445 225 851 433 717 = 1 * 139 583 862 445 + 86 267 571 272 139 583 862 445 = 1 * 86 267 571 272 + 53 316 291 173 86 267 571 272 = 1 * 53 316 291 173 + 32 951 280 099 53 316 291 173 = 1 * 32 951 280 099 + 20 365 011 074 32 951 280 099 = 1 * 20 365 011 074 + 12 586 269 025 20 365 011 074 = 1 * 12 586 269 025 + 7 778 742 049 12 586 269 025 = 1 * 7 778 742 049 + 4 807 526 976 7 778 742 049 = 1 * 4 807 526 976 + 2 971 215 073 4 807 526 976 = 1 * 2 971 215 073 + 1 836 311 903 2 971 215 073 = 1 * 1 836 311 903 + 1 134 903 170 1 836 311 903 = 1 * 1 134 903 170 + 701 408 733 1 134 903 170 = 1 * 701 408 733 + 433 494 437 701 408 733 = 1 * 433 494 437 + 267 914 296 433 494 437 = 1 * 267 914 296 + 165 580 141 267 914 296 = 1 * 165 580 141 + 102 334 155 165 580 141 = 1 * 102 334 155 + 63 245 986 102 334 155 = 1 * 63 245 986 + 39 088 169 63 245 986 = 1 * 39 088 169 + 24 157 817 39 088 169 = 1 * 24 157 817 + 14 930 352 24 157 817 = 1 * 14 930 352 + 9 227 465
Salakirjoitus 15 14 930 352 = 1 * 9 227 465 + 5 702 887 9 227 465 = 1 * 5 702 887 + 3 524 578 5 702 887 = 1 * 3 524 578 + 2 178 309 3 524 578 = 1 * 2 178 309 + 1 346 269 2 178 309 = 1 * 1 346 269 + 832 040 1 346 269 = 1 * 832 040 + 514 229 832 040 = 1 * 514 229 + 317 811 514 229 = 1 * 317 811 + 196 418 317 811 = 1 * 196 418 + 121 393 196 418 = 1 * 121 393 + 75 025 121 393 = 1 * 75 025 + 46 368 75 025 = 1 * 46 368 + 28 657 46 368 = 1 * 28 657 + 17 711 28 657 = 1 * 17 711 + 10 946 17 711 = 1 * 10 946 + 6765 10 946 = 1 * 6765 + 4181 6765 = 1 * 4181 + 2584 4181 = 1 * 2584 + 1597 2584 = 1 * 1597 + 987 1597 = 1 * 987 + 610 987 = 1 * 610 + 377 610 = 1 * 377 + 233 377 = 1 * 233 + 144 233 = 1 * 144 + 89 144 = 1 * 89 + 55 89 = 1 * 55 + 34 55 = 1 * 34 + 21 34 = 1 * 21 + 13 21 = 1 * 13 + 8 13 = 1 * 8 + 5 8 = 1 * 5 + 3 5 = 1 * 3 + 2 3 = 1 * 2 + 1 2 = 2 * 1 + 0 Viimeinen nollasta eroava jakojäännös = 1 = syt( 354 224 848 179 261 915 075, 218 922 995 834 555 169 026). Huomautus. Koska tässä lineaarikombinaatio u a + v b = 1, saadaan u a 1 = v b, ts. u a 1 (mod b) ja näin ollen u a -1 (mod b). Salakirjoituksissa tällaisilla käänteisalkioilla on hyvin keskeinen merkitys, kuten tullaan näkemään. Tämän viimeisen esimerkin tapauksessa lauseke u a + v b on (83621143489848422977)*354224848179261915075 + ( 135301852344706746049)* 218922995834555169026 = 1, joten 83621143489848422977 354 224 848 179 261 915 075-1 (mod 218922995834555169026), ts. 83621143489848422977*354224848179261915075 1 (mod 218922995834555169026).