|
|
Ten artykuł od 2010-03 wymaga uzupełnienia źródeł podanych informacji.
Informacje nieweryfikowalne potrafią zostać zakwestionowane oraz usunięte.
Aby uczynić artykuł weryfikowalnym, trzeba podać przypisy do materiałów opublikowanych w wiarygodnych źródłach. |
Algorytm Euklidesa – algorytm znajdowania największego wspólnego dzielnika (NWD) dwóch liczb naturalnych, nie wymagający rozkładania ich na czynniki pierwsze. Jego autorem jest Eudoksos z Knidos (IV wiek p.n.e.), Euklides zawarł go zaledwie w swoim dziele Elementy.
Podstawą algorytmu Euklidesa jest zależność:

Algorytm
Istnieją dwie równoważne implementacje algorytmu Euklidesa. Poniżej przedstawiono wersję obliczania NWD liczb a oraz b wykorzystującą operację reszty z dzielenia (modulo):
- oblicz c jako resztę z dzielenia a przez b
- zastąp pozycję a liczbą b, a pozycję b liczbą c
- jeżeli pozycja b = 0, to szukane NWD = a, w przeciwnym wypadku przejdź do 1
Implementacja
NWD(liczba całkowita a, liczba całkowita b)
dopóki b != 0
c := reszta z dzielenia a przez b
a := b
b := c
zwróć a
int NWD (int a, int b)
{
int c;
while (b != 0)
{
c = a % b;
a = b;
b = c;
}
return a;
}
Wersja rekurencyjna:
int NWD (int a, int b)
{
a=a%b;
if(a!=0)
return NWD(b,a);
else
return b;
}
static int NWD(int a, int b)
{
int c;
while (b != 0)
{
c = a % b;
a = b;
b = c;
}
return a;
}
function NWD(a, b) {
while (b != 0) {
var c = a % b;
a = b;
b = c;
}
return a;
}
function NWD ($a,$b)
{
$c=0;
while ($b != 0)
{
$c = $a % $b;
$a = $b;
$b = $c;
}
return $a;
}
Wersja algorytmu wykorzystująca operację odejmowania:
function nwd(a,b:integer):integer;
begin
while a<>b do
if a>b then a:=a-b else b:=b-a;
nwd:=a;
end;
nwd(A,0,A) :- !.
nwd(A,B,C) :- B1 is A mod B, nwd(B,B1,C).
Wersja algorytmu wykorzystująca operację odejmowania:
def nwd(a,b):
while a != b:
if a > b:
a = a - b
else:
b = b - a
return a
section .text
global getgcd
getgcd:
push ebp
mov ebp,esp
mov eax,ebp+8
mov ebx,ebp+12
petla:
cmp eax,ebx
jg wiekszy
jl mniejszy
jmp koniec
wiekszy:
sub eax,ebx
jmp petla
mniejszy:
sub ebx,eax
jmp petla
koniec:
mov esp,ebp
pop ebp
ret
oto nwd :a :b
dopóki nie :b = 0]
przypisz "c reszta :a :b
przypisz "a :b
przypisz "b :c]
wynik :a
już
Wersja rekurencyjna:
oto nwd :a :b
przypisz "a reszta :a :b
jeżeli nie :a = 0
wynik nwd :b :a]
wynik :b]
już
Przykłady
Obliczanie największego wspólnego dzielnika
Dla przykładu obliczymy największy wspólny dzielnik liczb 1071 oraz 1029, wykorzystując algorytm Euklidesa:

.
Tak więc:

Względna pierwszość
Jeżeli największym wspólnym dzielnikiem dwóch liczb jest 1, to są one względnie pierwsze. Przykład dla 46406 oraz 36957:
| a |
b |
| 46406 |
36957 |
| 36957 |
9449 |
| 9449 |
8610 |
| 8610 |
839 |
| 839 |
220 |
| 220 |
179 |
| 179 |
41 |
| 41 |
15 |
| 15 |
11 |
| 11 |
4 |
| 4 |
3 |
| 3 |
1 |
| 1 |
0 |
Otrzymaliśmy:
,
zatem liczby 46406 oraz 36957 są względnie pierwsze.
Dowód poprawności
Lemat: 
- Aby to wykazać, trzeba udowodnić, że wspólny podzielnik liczb
oraz
jest także podzielnikiem liczby 
- Przyjmijmy:


- gdzie
są liczbami całkowitymi.
- Wtedy:

- zatem
jest także podzielnikiem 
Z lematu wynika przez indukcję, że jeśli algorytm się zakończy, to da poprawny wynik. Pozostaje udowodnić, że się zakończy. Wystarczy w tym celu zauważyć, że
, więc w każdym kroku algorytmu wartość
zmniejsza się przynajmniej o 1. Gdyż nie może wcale być ujemna, algorytm musi się zakończyć.
Złożoność czasowa
Dla dowolnych liczb
algorytm Euklidesa zwraca wartość NWD(m, n) po co najwyżej
przebiegach pętli.
Dowód
- Lemat: Jeśli
to
- (1) jest równoważne

- Podstawiając

- otrzymuje się:

- i albowiem
to
, oraz ponadto z własności modulo
otrzymujemy:

- Przy pierwszej iteracji mamy
, po k-tym przebiegu pętli:
-

- Gdyż
, po ostatnim, l-tym przebiegu pętli będzie:
-




Największej liczby kroków algorytmu wymagają dwa kolejne elementy ciągu Fibonacciego.
Rozszerzony algorytm Euklidesa
Jeśli przechowywana będzie informacja o kolejnych ilorazach, to będzie też da się wyznaczyć liczby całkowite w równaniu
. Ta metoda nazywana jest rozszerzonym algorytmem Euklidesa.
Dla przykładu dla liczb 174 oraz 18 w algorytmie Euklidesa uzyskuje się wyniki pośrednie:



lub przepisując wszystkie równania w taki sposób, by w pierwszym równaniu po prawej stronie występowała tylko suma pewnych wielokrotności liczb 174 oraz 18:



Zauważmy, że w pierwszym równaniu po prawej stronie jest kombinacja liniowa liczb 174 oraz 18, analogicznie jak w równaniu
. W następnych równaniach po prawej stronie mamy stale kombinację liniową liczb 174, 18 albo liczb, które wystąpiły po lewej stronie we wcześniejszych równaniach.
Kluczowa dla rozszerzonego algorytmu Euklidesa staje się możliwość stopniowego zastępowania tych liczb przez kombinacje liniowe liczb wejściowych aż do otrzymania równości:

np.

Zapis algorytmu w pseudokodzie:
// Zakładamy, że a > 0 oraz b > 0.
a0 = a
b0 = b
// Inicjalizacja. Utrzymujemy niezmienniki p*a0 + q*b0 = a oraz r*a0 + s*b0 = b
p = 1; q = 0;
r = 0; s = 1;
// algorytm
while (b != 0)
c = a mod b
quot = floor( a/b )
a = b
b = c
new_r = p - quot * r
new_s = q - quot * s
p = r; q = s
r = new_r
s = new_s
// Wówczas NWD(a0, b0) = p*a0 + q*b0
Sprawdź też
Linki zewnętrzne