Algorytm Euklidesa
Algorytm
Algorytm Euklidesa pozwala na obliczenie największego wspólnego dzielnika (NWD) dwóch liczb a i b, gdzie obie liczby należą do zbioru liczb naturalnych. Metoda ta jest znacznie szybsze od wyszukiwania NWD na podstawie rozkładu wartości a i b na czynniki pierwsze.
W celu wyliczenia dwóch NWD dwóch liczb a i b należy je tak przyjąć, aby a ≥ b. Dopóki a ≠ b należy od a odjąć b. Po każdym odjęciu należy pamiętać, aby zamienić wartości a i b jeśli a < b. Po zakończeniu pętli NWD = a = b.
Przykład
Proces wyliczania NWD(138, 27) można rozpisać następująco:
NWD(138, 27) = NWD(138 - 27, 27) = NWD(111, 27) = NWD(84, 27) = NWD(57, 27) = NWD(30, 27) = NWD(3, 27) = NWD(27, 3) = NWD(3, 3) = 3
Ostatecznym wynikiem jest NWD(138, 27) = 3.
Implementacja
Odejmowanie
Algorytm Euklidesa można zapisać na wiele różnych sposobów. Jeden z nich polega na wykorzystaniu operacji odejmowania w celu uzyskania NWD:
1 2 3 4 5 6 7 8 9 10 | int nwd(int a, int b) { while (a != b) { if (a < b) { b -= a; } else { a -= b; } } return a; } |
1 2 3 4 5 6 7 8 9 10 | static int nwd(int a, int b) { while (a != b) { if (a < b) { b -= a; } else { a -= b; } } return a; } |
(1.) Funkcja nwd() przyjmuje dwa argumenty a i b. (2.) Dopóki oba argumenty są różne to (3. - 7.) należy odjąć mniejszą liczbę od większej. Na koniec (9.) wystarczy zwrócić a lub b. Jest to szukana wartość NWD(a,b). Warto zauważyć, że funkcja napotyka problem kiedy jedna z wartości wynosi 0. Wtedy program będzie działał w nieskończoność, ponieważ 0 nie będzie zmieniać wartości drugiej zmiennej, która będzie dodatnia, ponieważ wiadomo, że a i b należą do liczb naturalnych.
Modulo
Algorytm Euklidesa można też zapisać przy pomocy funkcji modulo. W tym przypadku będzie jednak potrzebna dodatkowe zmienna, która będzie przechowywać resztę z dzielenia a przez b. Tego typu rozwiązanie jest znacznie lepsze, ponieważ program oblicza szybciej ze względu na fakt, że przy kolejnych iteracjach jest sprawdzany tylko jeden warunek, a nie dwa. Jednak należy pamiętać, że w tym momencie program deklaruje dodatkową zmienną c, która zwiększa zapotrzebowanie programu na pamięć.
1 2 3 4 5 6 7 8 9 | int nwd(int a, int b) { int c; while (b != 0) { c = a % b; a = b; b = c; } return a; } |
1 2 3 4 5 6 7 8 9 | static int nwd(int a, int b) { int c; while (b != 0) { c = a % b; a = b; b = c; } return a; } |
(2.) Zmienna c pozwoli zapamiętać wynik a % b. (3.) Dopóki b jest różne od 0 to: (4.) zapisujemy w c wynik resztę z dzielenia a przez b. Jak wiadomo wynik tej operacji da liczbę, która będzie zarówno mniejsza od a jak i od b, dlatego wystarczy (5.) wartość b przypisać do a, a następnie (6.)b wartość c. W ten sposobób b < a, a co za tym idzie jeśli a = b to reszta z dzielenia a przez b to 0, a wtedy pętla zostaje przerwana, a a zawiera NWD(a,b).
Rekurencja
Algorytm Euklidesa można rozwiązać używając do wyliczeń rekurencji. Nie jest to metoda, która jest przejrzysta, ale spełnia swoje zadanie w tym przypadku. Kod wtedy można zapisać w zaledwie kilku linijkach:
1 2 3 4 5 | int nwd(int a, int b) { if (a == 0) return b; return nwd(b % a, a); } |
1 2 3 4 5 | static int nwd(int a, int b) { if (a == 0) return b; return nwd(b % a, a); } |
Testowanie funkcji
W celu przetestowania napisanych funkcji można skorzystać z poniższego fragmentu kodu:
1 2 3 4 5 6 7 8 9 | int main() { int a, b; cout << "Podaj wartości a i b\na = "; cin >> a; cout << "b = "; cin >> b; cout << nwd(a, b) << endl; return 0; } |
1 2 3 4 5 6 7 8 | static void Main(string[] args) { int a, b; Console.Write("Podaj wartości a i b\na = "); a = Convert.ToInt32(Console.ReadLine()); Console.Write("b = "); b = Convert.ToInt32(Console.ReadLine()); Console.WriteLine(nwd(a, b)); } |
- Kod źródłowy Odejmowanie
- Kod źródłowy Odejmowanie
- Kod źródłowy Modulo
- Kod źródłowy Modulo
- Kod źródłowy Rekurencja
- Kod źródłowy Rekurencja
Ćwiczenia
Zadanie 1
Napisz program, który wczyta od użytkownia dwie liczby a i b, a następnie wykorzystując dowolny sposób obliczy NWD podanych liczb. W przypadku, gdy wprowadzone są błędne to należy wypisać na ekranie odpowiedni komunikat.
Zadanie 2
Zapisz algorytm Euklidesa przy użyciu jak najmniejszej liczby znaków.