• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Rekurencja a iteracja :D

Object Storage Arubacloud
0 głosów
6,366 wizyt
pytanie zadane 16 maja 2015 w C i C++ przez Wiciorny Ekspert (270,910 p.)
Siemanko robiłem zadanie z odc. 13. Dla ciągu fibonacciego, metodą rekurencji i iteracji.

Otóż-  wyszło mi, że iteracja jest o wiele szybsza o dziwo? Dla 44 wyrazu ciągu 4 sekundy zajęło obliczenie rekurencji natomiast iteracji 0.001, jakim cudem tak rozbierzny wynik? Za każdym razem iteracja jest szybsza  :D a to przecież rekurencje stosujemy w przypadku przyspieszenia pracy kosztem pamięci

4 odpowiedzi

+2 głosów
odpowiedź 17 maja 2015 przez Bartek85 Mądrala (7,440 p.)
edycja 17 maja 2015 przez Bartek85

To zależy. I nie ma reguły, że rekurencja będzie zawsze szybsza od metody iteracyjnej i na odwrót. Są zagadnienia, które lepiej się rozwiązuje metodą rekurencyjną, a czasami lepiej jest użyć innej metody, np. iteracyjnej.

"Czy ferrrari z silnikiem od fiata 126p, będzie szybsze niż fiat 126p z silnikiem ferrari?"

To pytanie zostawie dla Was...

Szybkość wykonania programu, zależy tylko od programisty! Od tego jak wykorzystuje zasoby komputera, jaki napisze alogorytm i oczywiście jaką ma znajomość działania komputera. Rekurencja pomimo wielu zalet, ma też poważne wady. Np. to, że ilośc wywołań jest ograniczona wielkością stosu(tutaj zapraszam do lektury na temat stosu i sterty).

Różnica którą zaoberwowałeś w swoim kodzie wynika pewnie z mało optymalnej metody. Pozwolę sobie wkleić kod użytkownika Radfler. Z czasu wykonania pewnie wynika, że u siebie masz podobną implementację.

//Metoda rekurencyjna
unsigned long long fib(unsigned long long n)
{
    if(n > 2)
        return fib(n-1) + fib(n-2);
    return 1;
}

//Metoda iteracyjna
unsigned long long fib_i(int num) { 
    unsigned long long x=1, y=1;
    while(--num) x = (y += x) - x;
    return x;
}

Moja implementacja:

//Zoptymalizowana rekurencja
unsigned long long fib_optimized(int n, unsigned long long n1 = 1, unsigned long long n2 = 1)
{	
	if(n == 2)
		return n2;
	return fib_optimized(n - 1, n2, n1 + n2);
}

Jak widac na powyższym przykładzie, rekurencja może być tak samo szybka jak metoda iteracyjna, albo nawet i szybsza... Wszytsko zależy od programisty!

0 głosów
odpowiedź 16 maja 2015 przez Radfler VIP (101,030 p.)
edycja 17 maja 2015 przez Radfler
Daj kod, bo aż uwierzyć nie mogę :o
komentarz 16 maja 2015 przez hit02 Nałogowiec (33,970 p.)

Zazwyczaj rekurencja jest wolniejsza, bo obliczenia się powtarzają. smiley

komentarz 16 maja 2015 przez Radfler VIP (101,030 p.)

Rzeczywiście, sam napisałem taki program i wynika z niego, że rekurencja dla większych elementów jest wolniejsza o nawet sekundę :/

#include <iostream>
#include <ctime>
using namespace std;

inline int fib_r(int num) {

    return (num < 3) ? (1) : fib_r(num-2)+fib_r(num-1);
}

int fib_i(int num) {

    int x=1, y=1;
    while(--num) x = (y += x) - x;
    return x;
}

int main() {

    const int nr_wyrazu = 40;

    double start, stop; // double zamiast clock_t (czyli long)
    int rezultat;

    cout.precision(20); // Precyzja wypisywania

    // Około 1.9530000000000000693 sekundy
    start = clock();
    rezultat = fib_r(nr_wyrazu);
    stop = clock();
    cout << "Czas [metoda rekurencyjna]: " << (stop-start) / CLOCKS_PER_SEC
         << "\trezultat = " << rezultat << endl << endl;

    // 0 sekund
    start = clock();
    rezultat = fib_i(nr_wyrazu);
    stop = clock();
    cout << "Czas [metoda iteracyjna]: " << (stop-start) / CLOCKS_PER_SEC
         << "\trezultat = " << rezultat << endl << endl;
}

 

0 głosów
odpowiedź 16 maja 2015 przez hit02 Nałogowiec (33,970 p.)

Zapewne funkcja rekurencyjna wygląda tak:

int fib(int n)
{
    if(n > 2)
        return fib(n-1) + fib(n-2);
    return 1;
}

Narysuj sobie drzewo wywołań funkcji nawet dla niewielkich wyrazów, a zobaczysz, że część obliczeń się powtarza. Przy 44 wyrazie powtórzeń jest tak wiele, że kod wykonuje się setki razy dłużej niż dla iteracji.

Moim zdaniem rekurencja nie jest w żaden sposób wydajniejsza, ale zapisany algorytm jest bardzo zgrabny, natomiast iteracja nie wygląda tak pięknie ale kod jest często dużo szybszy i nie zużywa tak wiele pamięci.

0 głosów
odpowiedź 16 maja 2015 przez Kuba Stary wyjadacz (12,460 p.)
To nie dziwne. Dodawanie jest bardzo 'przyjemne' dla procesora. Poczytaj sobie jak działa na przykład mnożenie, albo napisz sobie coś na liczenie silni obydwoma sposobami.

Podobne pytania

0 głosów
1 odpowiedź 989 wizyt
pytanie zadane 11 listopada 2018 w C i C++ przez Shimeo7 Obywatel (1,910 p.)
0 głosów
3 odpowiedzi 3,990 wizyt
pytanie zadane 31 lipca 2015 w Algorytmy przez broda Początkujący (380 p.)
0 głosów
0 odpowiedzi 385 wizyt
pytanie zadane 30 września 2017 w JavaScript przez avrack4 Początkujący (370 p.)

92,634 zapytań

141,505 odpowiedzi

319,883 komentarzy

62,015 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...