[C] rekurencja końcowa oblicznie silni - funkcje

0
long rsilnia(int n)
{
        long odp;
        if(n>0)
              odp=n*rsilnia(n-1);
        else
              odp=1;
        return odp;
}

nie rozumiem tu tego obliczenia.
i takiej funkcji nie mogę zrozumieć

ale np. chce obliczyć 3 silnia więc w funkcji będzie n=3
idąc poklei
I poziom
n>0 prawda
odp=3rsilnia(2)
przechodzimy do
II poziom
2>0
odp=3
rsilnia(1)
III poziom
1>0
odp=3*rsilnia(0)
IV poziom
0>0 nie prawda

ponieważ jest to fałsz to teraz chyba się cofa z tymi poziomami
tylko ze ta funkcja nic jeszcze nie policzyła więc n*rsilnia(n-1)
przez to n ma byc mnożone

0
Foxtrot napisał(a):

IV poziom
0>0 nie prawda

ponieważ jest to fałsz to teraz chyba się cofa z tymi poziomami
tylko ze ta funkcja nic jeszcze nie policzyła więc n*rsilnia(n-1)

ponieważ jest to fałsz, to przypisuje się do odp=1 i zwraca, wtedy wraca ta funkcja z wartością 1... potem zwija się dalej z 1 * 2 ... itd.

0

Możesz mi to jakoś rozpisać bo nie rozumiem.
Poza tym jak zwraca odp=1 to co bym nie wpisał to zawsze powinno dać 1
i nie widzę żadnego mnożenia 1*2

0
Rsilnia(3) → (3 > 0) = return 3 * 2 (dolne wywolanie zwrocilo 2 więc zwracasz 3 * silnia(2) = 3 * 2 * 1 * 1 = 3 * 2  
   Rsilnia(2) → (2 > 0) = return 2 * 1 (dolne wywolanie zwrocilo 1 więc zwracasz 2 * silnia(1) = 2 * 1 * 1 = 2 )
      Rsilnia(1) → (1>0) = return 1 * 1 (dolne wywolanie zwrociło 1 więc zwracasz 1 * Rsilnia(0) = 1 * 1 = 1 )
         Rsilnia(0) → (0 > 0) = return 1 (fałszy więc odp = 1, bo masz else odp = 1)

przy okazji widać, że niepotrzebnie wywoływana jest funkcja Rsilnia(0) ponieważ jest ona równa tyle samo co Rsilnia(1) ponieważ z definicji silni 0! = 1! = 1 czyli możesz zaoszczędzić jedno wywołanie.

Czytaj najlepiej od dołu bo jak spojrzysz na swój kod to aż do wywołania Rsilnia(0) wywołujesz kolejno Rsilnia(3), Rsilnia(2), Rsilnia(1) i dopiero Rsilnia(0), które zwraca 1. (teraz przechodzi z powrotem do Rsilnia(1) i jest obliczana dalej wartość - idziesz w góre schematu - czyli odczytujesz kolejne return'y ze schematu.

0

Rsilnia(0) → (0 > 0) = return 1

dlaczego zwraca1 i dlaczego wyżej jest 1*1, i dlaczego ja jest odp=1 to i tak da inny wynik

0
        if(n>0)
              odp=n*rsilnia(n-1);
        else
              odp=1;
    return odp;

gdy n == 0 to co zostanie przypisane do odp i zwrócone przez funkcje?

0

no odp=1 i zwraca ten wynik
więc skoro wynik już to poco dalej liczy ale nawet jeśli liczy dalej to wraca i mamy 1=5*rsilnia(0)

0

no to może tak, prześledź w jaki sposób jest ta funkcja wywoływana.

long silnia(int n)
{
    long d = 0;
    printf("wywolano silnia( %d )\n", n);
    if(n > 0)
    {
        printf("silnia( %d ) = %d * silnia( %d )\n", n, n, n - 1);
        d = n * silnia(n - 1);
    }

    else
        d = 1;

    printf("silnia( %d ) zwraca wartosc: %d \n", n, d);
    return d;
}
5

@Foxtrot nie wysilaj się. Słyszałem że niektórym ludziom po prostu brakuje tego kawałka mózgu związanego z rekurencją i wskaźnikami. Dotąd myślałem że to taki żart, ale teraz widzę że to jest szczera prawda.

0

wszystko fajnie ale dalej nie widzę tego mnożenia
dla n 5
jest zwracane kolejno
silnia 0 zwraca 1
silnia 1 zwraca 1
silnia 2 zwraca 2
silnia 3 zwraca 6
silnia 4 zwraca 24
silnia 5 zwraca 120

ale skąd się te wartości biorą

1

Ostatnia moja próba:

Masz 4 karty z napisami:
karta I: silnia(3) = 3 * x
karta II: silnia(2) = 2 * x
karta III: silnia(1) = 1* x
karta IV: silnia(0) = 1 //to wiesz z definicji oraz z tego else'a z kodu programu

teraz odkładasz po kolei karty na kupkę zaczynając od karty I.
Czyli masz kupkę na, której spodzie znajduje się karta nr I a na wierzchu karta nr IV.
Twoim zadaniem jest wprowadzić odpowiednią liczbę zamiast x. (czyli przepisać wynik mnożenia z karty którą zabrałeś jako ostatnią – nie licząc tej którą trzymasz w ręce) czyli:

Bierzesz pierwszą kartę z wierzchu czyli karta nr IV – nic nie dopisujesz bo już masz tam wpisaną wartość 1

Bierzesz drugą kartę (kartę nr III) i podstawiasz za x wynik mnożenia z poprzedniej karty, którą zabrałeś (karty nr IV ). Ponieważ na poprzedniej karcie było 1 to na tej widnieje teraz zapisz silnia(1) = 1 * 1

Bierzesz trzecią kartę (kartę nr II) i podstawiasz znowu za x wynik mnożenia z poprzedniej karty (czyli 1 * 1) i tak na karcie nr II widnieje teraz napisz (silnia(2) = 2 * 1)

Bierzesz ostatnią kartę z kupki (kartę nr I) i podstawiasz po raz kolejny wynik mnożenia z ostatniej karty (czyli 2 * 1), w tej chwili na karcie nr I widnieje napis (silnia(3) = 3 * 2) – ponieważ nie masz już więcej kart ta karta jest wynikiem twojego algorytmu.

0

wszystko fajnie ale dalej nie widzę tego mnożenia
dla n 5
jest zwracane kolejno
silnia 0 zwraca 1
silnia 1 zwraca 1
silnia 2 zwraca 2
silnia 3 zwraca 6
silnia 4 zwraca 24
silnia 5 zwraca 120

ale skąd się te wartości biorą

Ty w ogóle wiesz co to jest silnia?
Na wszelki wypadek to wszystkie liczy od 1 przemnozone az do danej liczby czyli 3!(silnia) to 123
Jeszcze wyjatek silnia 0 to 1

Rekurencja dziala na takiej za sadzie ze funkcja zwraca sama siebie.

int Silnia(int liczba){
if( liczba == 1 || liczba == 0) return 1; // czyli jesli chcesz obliczyc silnie jeden lub zero to zroci jeden np. Silnia(1) = 1
else return ( liczba * Silnia(liczba -1) );// w tym przypadku np Silnia(3) = 3*Silnia(3-1) a silnia (3-1) = 2*silnia(2-1),a silnia(2-1) = silnia(1) = 1  i teraz jedziesz od prawej do lewej 1*2*3 = 6 , stad silnia 3 zwraca 6
}
 
0

Chyba rozumiem tylko jeszcze jedna żecz
dla n=3

I poziom
n>0 prawda
       odp=3*rsilnia(2)
przechodzimy do
II poziom
2>0
       odp=2*rsilnia(1)
III poziom
1>0
       odp=1*rsilnia(0)
IV poziom
0>0 nie prawda 
więc odp=1;

return odp;

więc jest tak że IV poziom zwraca 1 bo tak jest w else
ale pisze return odp. więc dlaczego to 1 podstawia pod rsilnia 2 w III poziomie a nie pod odp

bo z tego co tłumaczysz
IV poziom zwraca 1
i w III poziomie będzie odp=11=1 zwraca 1
i w II poziomie będzie odp=2
1=2 zwraca 2
i w I poziomie bezie odp-3*2=6 zwraca 6

a mi cały czas to wygląda że ja
IV poziom zwraca jeden to w
III poziomie powinno być
1=1*rsilnia(0) bo jest return odp

0

do zmiennej odp masz przypisaną WARTOŚĆ wyrażenia n * silnia(n-1), czyli dla n = 1 WARTOŚĆ wyrażenia wyniesie 1 .

0

A to odp jest zmienną lokalną, tzn. istnieje tylko w funkcji wywoływanej. Nie przechodzi do funkcji wywołującej. Funkcje nie zwracają wartości przez zmienne lokalne.

W twoim przykładzie, w trzecim poziomie, wartość zwracaną przez rsilnia(0) podstawiasz za rsilnia(0), a nie za odp.
odp=1*1 a nie 1=1*rsilnia(0)

Myślę, że problem nie leży w zrozumieniu rekurencji, tylko właśnie zasad działania funkcji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1