Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Ponavljanje main funkcije

[es] :: C/C++ programiranje :: Ponavljanje main funkcije

Strane: 1 2 3 4

[ Pregleda: 10289 | Odgovora: 61 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Boyka
BPS

Član broj: 287185
Poruke: 338
*.dynamic.isp.telekom.rs.



+33 Profil

icon Re: Ponavljanje main funkcije28.10.2012. u 17:56 - pre 139 meseci
Citat:
chaami:
@Mihajlo neće se stek nikad popuniti jer ga return prazni od predhodne funcije tako da možeš do penzije da unosiš brojeve (uključi debug i videćeš da je uvek samo jedna funkcija na steku).

@Goran upravo zato i jeste "lepo" jer rekurziju koristimo bukvalno kao goto ;)


goto je u stvari jedna rekurzivna metoda sa get, set parametrima...
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije28.10.2012. u 18:02 - pre 139 meseci
Nije. Probaj da isprogramiraš izračunavanje vrednosti matematičkih izraza sa zagradama bez rekurzije. Može bez rekurzije, ali ti treba stek, koji predstavlja fundamentalnu razliku između rekurzije i goto naredbe.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Ponavljanje main funkcije29.10.2012. u 18:46 - pre 139 meseci
Meni samo nije jasno zašto bi neko morao da se oslanja na bilo kakvu vrstu optimizacije koja nije invarijantna. To je jednostavno loše u 90% slučajeva. U preostalih 10%, onaj ko to radi, vrlo dobro zna šta radi ili nema blage veze šta radi. Za rekurziju UVEK treba definisati bazni slučaj, a ne oslanjati se na tail recursion optimizaciju. To je isto kao kada bi neko hteo da broji kopije nekog objekta u statičkoj promenljivoj njegove klase koju bi inkrementirao u copy konstruktoru recimo... Neko je postavljaču teme ponudio rešenje sa while petljom koje smatram mnogo boljim neko rekurzivno pozivanje main-a, ma koliko optimalno bilo...
 
Odgovor na temu

Boyka
BPS

Član broj: 287185
Poruke: 338
*.dynamic.isp.telekom.rs.



+33 Profil

icon Re: Ponavljanje main funkcije29.10.2012. u 19:44 - pre 139 meseci
@Nedeljko mislio sam za petlje, kontam da su petlje u stvari neke rekurzivne metode?

Evo i sa goto, krenuo i ja sa c, pa cisto da vidim da li znam ista :lol:
Code (c):

int main()
{
pocetak:
     int x;
     printf("Unesi broj (za izlaz unesi 0) :\n");
     scanf("%i",&x);
     if(x%2==0) printf("PARAN\n");
     else printf("NEPARAN\n");
     while(x!=0)
     {
          goto pocetak;
     }
}
 
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 12:50 - pre 139 meseci
Citat:
Goran Arandjelovic: Za rekurziju UVEK treba definisati bazni slučaj, a ne oslanjati se na tail recursion optimizaciju.

Kakve veze ima rekurzija sa optimizacijom? Rekurzija je svođenje složenih slučajeva na proste u nekom broju koraka, pri čemu se rešavaju neposredno. Štaviše, rekurzija po pravilu daje manje efikasna rešenja od iterativnih.

Primer: Izračunavanje elemenata Fibonačijevog niza:
Code (cpp):
int fib_recursive(int k)
{
    if (k == 1 || k == 2) {
        return 1;
    } else if (k > 2) {
        return fib_recursive(k - 1) + fib_recursive(k - 2);
    } else {
        throw("error");
    }
}

int fib_iterative(int k)
{
    if (k < 1) {
        throw("error");
    }

    int a0 = 0, a1 = 1;

    for (int i = 1; i < k; ++i) {
        int t = a0 + a1;

        a0 = a1;
        a1 = t;
    }

    return a1;
}

Rekurzivna funkcija se računa u eksponencijalnom vemenu i linearnom prostoru (računajući nagomilavanje steka), a iterativno u linearnom vremenu i konstantnom prostoru. Za iterativno rešenje je lako proceniti složenost. Rekurzija uvek izbacuje rezultat 1 kada se slučaj ne svodi na prostiji, tako da će se sve svesti na sabiranje jedinica. Primera radi

fib(5)=fib(4)+fib(3)
=(fib(3)+fib(2))+(fib(2)+fib(1))
=((fib(2)+fib(1))+1)+(1+1)
=((1+1)+1)+(1+1)

Ko ne veruje, može da ubaci brojače i dobiće da je broj sabiranja koji se obavi za izračunavanje fib(k) tačno fib(k)-1, a broj neposrednih izračunavanja tačno fib(k). No, poznato je da Fibonačijev niz eksponencijalno brzo raste, tako da je vreme izvršavanja eksponencijalno. Korišćeni prostor je linearan, jer za k>2 nema rekurzivnih spustova koji su duži od k-2 (argument se uvek smanjuje za 1), a postoji rekurzivni spust dužine k-2 (u izračunavanju fib(k) se koristi izračunavanje od fib(k-1) u čijem se izračunavanju koristi fib(k-2) itd.).

Kada rekurziju treba koristiti? Skoro nikad. Ako ne postoji potreba za gomilanjem steka, to treba rešiti petljom. Sledeći primer pronalazi prvi član neopadajućeg niza koji nije manji od date vrednosti:
Code (cpp):
int binary_search(double value, double array[], int size)
{
    int left = 0, right = size;

    while (left < right) {
        int mid = (left + right) >> 1;

        if (array[mid] < value) {
            left = ++mid;
        } else {
            right = mid;
        }
    }

    return left;
}

Kada se stek gomila, a nemamo kontrolu koliko može da se gomila, ni slučajno ne koristiti rekurziju, već ako je algoritam baš prirodno rekurzivan, onda simulirati rekurziju korišćenjem dinamičkog steka (flood fill, rešavanje lavirinta itd). Nju treba koristiti samo u slučaju da se stek gomila do neke kontrolisane granice, a takvi slučajevi su retki (razna balansirana stabla, minimaks algoritam za igranje igara kao što je šah itd).
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 12:52 - pre 139 meseci
Boyka, ne valja ti program. Hajde, proveri ga i ispravi. Neće se izvšiti petlja više od jedanput.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
80.93.235.*



+9 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 15:27 - pre 139 meseci
Citat:
Nedeljko:
Kakve veze ima rekurzija sa optimizacijom? Rekurzija je svođenje složenih slučajeva na proste u nekom broju koraka, pri čemu se rešavaju neposredno. Štaviše, rekurzija po pravilu daje manje efikasna rešenja od iterativnih.


Ako bi malo bolje čitao, ne bi me takvu glupost ni pitao samo da bi trolovao, ali avaj, da se nadovežem:
Pošto ne mora da bude poznato koliko će rekurzivnih poziva biti, u nekom trenutku može da se prepuni stek, pa sam zato pomenuo da ne treba računati na optimizaciju koja će "obrisati" f-ju, tj. eleminisati pravljenje novih stek frejmova.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 16:26 - pre 139 meseci
Sad sam izguglao "tail recursion optimisation". No, kakve to ima veze sa nedefinisanjem baznih slučaja? Bazne slučajeve moraš da imaš, osim ako želiš beskonačnu rekurziju.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
80.93.235.*



+9 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 16:49 - pre 139 meseci
Čekaj, sad ti je jasnije šta sam rekao ili ne? Pošto brzo menjaš svoje odgovore pa nisam stigao da pročitam.

Code:

void func()
{
    // ...
    func();
}

int main()
{
    func();
}


Ovo je beskonača rekurzija koja će prepuniti stek, ali ako se uključi O2/O3 optimizacija, onda neće. Takođe, ako je optimizacija isključena, može se desiti da se stek napuni pre svođenja na bazni slučaj. Je l' sad jasnije ili ne? A mogao si i ranije da izguglaš šta znači tali recursion optimizacija pre nego što saspeš kako ne razumeš šta sam napisao.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 17:30 - pre 139 meseci
Takvu beskonačnu rekurziju kakvu si naveo, ti nikada ne bi napisao u kodu. Je li tako? E, ako je tako, čemu uopšte komentarisanje takvih "tehnika"? Korišćenje beskonačne rekurzije umesto beskonačne petlje je za momentalan otkaz. Takođe, i dalje ne vidim vezu sa nedefinisanjem baznih slučajeva.

Kada rekurziju treba koristiti, napisao sam. Vrlo retko, a kada se koristi, uvek treba da postoji izlaz iz rekurzije. Nije bitno samo da se direktno reše bazni slučajevi, već i da se ostali slučajevi zaista svode na bazne. Primer:
Code (cpp):

int fib(int k)
{
    if (k < 1) {
        throw("error");
    }

    if (k == 1) {
        return 1;
    }

    return fib(k - 1) + fib(k - 2);
}

Ovaj kod je pogrešan jer baca izuzetak za sve ulaze različite od 1. Džaba definisanje baznih slučajeva, ako se ostali ne svode na njih.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
80.93.235.*



+9 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 18:47 - pre 139 meseci
Aman čoveče, čitaj šta pišem, a batali ono o čemu ne pišem.

Code:

int fact(int n)
{  
    if(n <= 1)
        return 1;
    
    return(n * fact(n - 1));
}


Dakle, najprostija rekurzivna funkcija koju bi neko mogao da napiše ovako, zar ne?
Za dovoljno veliko n, poziv ove f-je može teoretski da napuni stek i program puca, a ako je optimizacija uključena na kraju ćeš samo dobiti pogrešan rezultat zbog prekoračenja.
Šta ti dalje nije jasno?
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije30.10.2012. u 20:24 - pre 139 meseci
Nije mi jasno zašto se nerviraš. OK, isprva nisam proverio šta je optimizacija repa rekurzije, posle sam video. OK.

Što se ovog programa tiče, testirao sam ga i radi, ali nemam pojma kako. Koliko vidim, nakon izračunavanja rezultat mora da se pomnoži sa n, koje nije isto kroz sve pozive po dubini, tako da mi nije najasnije kako može da ne gomila stek, ali ga ne gomila.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

chaami
Goran Petrović
nezaposlen
Beograd

Član broj: 262685
Poruke: 84
*.mediaworksit.net.



+28 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 00:25 - pre 139 meseci
@Nedeljko evo ga primer koji će i sa optimizacijom da puni stek.

Code:

float fun(float n)
{
    if(n <= 1)
        return 1;
    return n/fun(n-1);
}


Kod množenja je svejedno sa koje strane računamo dok kod deljenja nije, tako da u ovom slučaju nema ništa od optimizacije.

Izgleda da nisam bio u pravu kad sam tvrdio da ako na izlazu funcija pozove samu sebe da nema opasnosti od pretrpavanja steka :)

@Goran Za O3 optimizaciju znam da često možemo imati više štete nego koristi ukoliko neznamo šta radimo. Inline funkcije koje ta optimizacija pravi često mogu da naprave glomazne objekte koji uveliko premašuju instrukcijski keš. Interesuje me zašto smatraš da je O2 optimizacija loša stvar. Voleo bi da mi daš neki konkretan primer. Ovaj primer koji si naveo mi baš i nije jasan.Koliko vidim u praksi ćemo čak i sa 64-bitnim intidžerom i sa optimizacijom i bez nje dobiti pogrešan rezultat već sa 26. Ukoliko pretpostavimo da imamo neku imaginarnu mašinu sa neograničenim intidžerom u tom slučaju će program bez optimizacije zaista pući kod velikog unosa. Program sa optimizacijom neće pući već će bez obzira na veličinu unosa dati tačan rezultat. Ukoliko čak i dođe do situacije koju si naveo imaćemo dva potpuno neupotrebljiva programa (koje su napravili loši programeri).
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
80.93.235.*



+9 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 13:02 - pre 139 meseci
@chaami
Ma primer koji sam naveo je samo veštački i ne baš realan, zauzima malo prostora na steku u jednom pozivu f-je, tako da ni posle tih graničnih 26 (overflow granica) rekurzivnih poziva stek sigurno neće biti popunjen, ali samo kažem da postoji mogućnost da se stek popuni pre svođenja na bazni slučaj. Nisam rekao da je O2 optimizacija loša samo sam u trenutku zaboravio da li je inlajnovanje u okviru O2 ili O3. Nego, evo ga jedan primer, a vrlo brzo ćeš da pogodiš koja optimizacija može da prouzrokuje neočekivane rezultate.

Code (cpp):

struct A
{
    A() {}
    A(const A &a) { ++count; }

    static int count;
};

int A::count = 0;

A func1()
{
    A ret;
    // ...
    return(ret);
}

void func2(A arg)
{
    // ...
}

int main()
{
    A obj;
    func2(obj);
    func2(func1());

    cout << A::count;

    return(0);
}
 


U tom smislu sam govorio kako treba biti upoznat sa optimizacijama koje se uključuju, a ne da neko lupi bilo šta pa se posle češe po glavi.
 
Odgovor na temu

kosta90s
Freelancer programmer
Srbija

Član broj: 306289
Poruke: 27
212.178.224.*



+3 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 17:20 - pre 139 meseci
Code (c):
main()
{
      int x;
while(1)
{    
      printf("Unesi broj (za izlaz unesi 0) :\n");
      scanf("%i",&x);
     if(x==0)
          break;
      if(x%2==0)
      printf("PARAN\n");
      else
      printf("NEPARAN\n");

}
     
}

Zasto koristis break kad ne moras? Licno smatram da break treba izbegavati.
Evo mog nacina
Code (c):

#include <stdio.h>

int main(void)
{
      int x=1;
      while(x!=0)
      {    
           printf("Unesi broj (za izlaz unesi 0) :\n");
           scanf("%d",&x);
           if(x%2!=0)
           {
                printf("NEPARAN\n");
           }
           else if(x!=0)
           {
                printf("PARAN\n");
           }
      }
      return(0);  
}


[Ovu poruku je menjao kosta90s dana 31.10.2012. u 18:38 GMT+1]
 
Odgovor na temu

Boyka
BPS

Član broj: 287185
Poruke: 338
*.dynamic.isp.telekom.rs.



+33 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 17:38 - pre 139 meseci
Citat:
Nedeljko:
Boyka, ne valja ti program. Hajde, proveri ga i ispravi. Neće se izvšiti petlja više od jedanput.


Meni odlicno radi care...
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
80.93.235.*



+9 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 17:55 - pre 139 meseci
Tebi program "odlično" radi, ali hajde malo razmisli, da li bi bilo razlike da si umesto while-a stavio if?
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8632
*.3gnet.mts.telekom.rs.



+2789 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 18:14 - pre 139 meseci
Niko da mi objasni kako radi ona funkcija za faktorijel bez nagomilavanja steka.

Boyka, tvoj program odlično radi, ali šta radi? Probaj da ga jednom pokreneš i da uneseš nekoliko brojeva.
Citat:
kosta90s: Zasto koristis break kad ne moras? Licno smatram da break treba izbegavati.

Zašto smatraš da ga treba izbegavati?
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

kosta90s
Freelancer programmer
Srbija

Član broj: 306289
Poruke: 27
212.178.224.*



+3 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 18:30 - pre 139 meseci
@Nedeljko
Citat:
Zašto smatraš da ga treba izbegavati?


Zato sto se upotrebom naredbe break narusava strukturiranost koda.

[Ovu poruku je menjao kosta90s dana 31.10.2012. u 21:31 GMT+1]
 
Odgovor na temu

Boyka
BPS

Član broj: 287185
Poruke: 338
*.dynamic.isp.telekom.rs.



+33 Profil

icon Re: Ponavljanje main funkcije31.10.2012. u 18:31 - pre 139 meseci
Citat:
Goran Arandjelovic:
Tebi program "odlično" radi, ali hajde malo razmisli, da li bi bilo razlike da si umesto while-a stavio if?


Nepotrebni while definitivno :)

@Nedeljko
@Goran

Je'l mozete samo da skoknete do teme http://www.elitesecurity.org/t456741-0#3190852 moj poslednji post, zanima me gde to gresim u C-u, program odlicno radi u C# i zavrsio sam ga za 2-3 minuta, ali u C nemam pojma, jer sam treci dan u C jeziku, bas me zanima gde sam pogresio.
 
Odgovor na temu

[es] :: C/C++ programiranje :: Ponavljanje main funkcije

Strane: 1 2 3 4

[ Pregleda: 10289 | Odgovora: 61 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.