Funkcia v C - faktorial

vilém

Funkcia v C - faktorial
« kdy: 15. 07. 2013, 10:45:41 »
Dobry den,

Vymyslel som si priklad na pouzivanie funkcii v jazyku C. Je to faktorial zadaneho cisla. Cize chcem aby mi napr pre 4! zobrazilo 4!=1x2x3x4.

Zdrojak udavam:

Kód: [Vybrat]
#include <stdio.h>

int otrok (int a)
{
  int i = 0;
  while ( i < a)
    i++;
  return i;
}

int main ()
{
  int i, j;
  printf ("Ja som mudry pocitac a viem zobrazit postupne cisla zadaneho faktorialu.\n");
  printf ("Zadaj cislo na zobrazenie vypoctu faktorialu: ");
  scanf ("%d", &i);
  printf ("\n");
  printf ("%d! = ", i);
  while (i >= 1)
  {
    j = otrok (i);
    printf ("%d", j);
    if (j > 0)
    {
      printf (" x ");
      i--;
    }
  }
  printf ("\n");
  printf ("\n");
}

Ono by to aj fungovalo. Po dvoch hodinach "maturovania" nad problemom som na nieco aj prisiel, ale cisla zobrazuje v opacnom poradi. (4! = 4x3x2x1)
Poprosil by som Vas znalych, aby ste mi pomohli s identifikaciou chyby.

Dakujem
« Poslední změna: 15. 07. 2013, 12:00:08 od Petr Krčmář »


matusss

Re:funkcia v C - faktorial
« Odpověď #1 kdy: 15. 07. 2013, 11:16:08 »
Ahoj,

v cykle while (i >= 1) ides od i po 1. Pouzi v cykle novu premennu a chod s nou od 1 po i.

Po dalsie si pomenovavaj premenne aspon celymi slovami (pripadne aj viacslovne), neboj sa dlhsich nazvov, tvoj kod bude ovela citatelnejsi (kym nebudu nazvy cez polku monitora :D )

(este by som vytkol ze funkcia otrok vrati cislo, ktore dostane ako parameter, skus radsej spravit funkciu, ktorej posles cislo a ona vypise cely zoznam tych cisel (bude v nej cely tvoj while))

nuda

Re:funkcia v C - faktorial
« Odpověď #2 kdy: 15. 07. 2013, 11:16:51 »
No ved ta funkcia otrok Ti vrati furt o jedno mensie ako predchadzajuca hodnota... cize to robis odzadu :D
ja by som v maine zmazal celu while pasaz, a funkciu otrok prerobil tak, aby v kazdom cykle po zvyseni i++, vysledok hned aj vypisala... cize take nieco(pseudo):

while(i<a)
{
  i++;
  print(i);
}

a v maine miesto tvojej while pasaze, iba dosad
otrok(zadaneCisloOdUzivatela);

tie detaily ako "x"za kazdym cislom a kecy okolo si hadam dorobis...

rob

Re:funkcia v C - faktorial
« Odpověď #3 kdy: 15. 07. 2013, 11:19:35 »
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>

int main() {
    int faktorial;
    printf("Zadej faktorial: ");
    if ( scanf ("%d", &faktorial) != 1 ) {
        printf("Spatny vstup.\n");
        return 1;
    }
    printf("\n");
    printf("%d=", faktorial);
    for( int i = 1;i < faktorial;++i) {
        printf("%dx", i);
    }
    printf("%d\n", faktorial);
    return 0;
}

insider

Re:funkcia v C - faktorial
« Odpověď #4 kdy: 15. 07. 2013, 11:23:18 »
Nebylo by lepsi pouzit for cyklus? Kde zapisem for(j = 1;j <= i;j++) bys dostal posloupnost j = 1;...;j = i a tedy ve vypise pak 1x*x*... samozrejme whilem to vyjde nastejno, ale musis si hlidat ten radek s i--


vilém

Re:funkcia v C - faktorial
« Odpověď #5 kdy: 15. 07. 2013, 11:45:48 »
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>

int main() {
    int faktorial;
    printf("Zadej faktorial: ");
    if ( scanf ("%d", &faktorial) != 1 ) {
        printf("Spatny vstup.\n");
        return 1;
    }
    printf("\n");
    printf("%d=", faktorial);
    for( int i = 1;i < faktorial;++i) {
        printf("%dx", i);
    }
    printf("%d\n", faktorial);
    return 0;
}

Rob, ono ma to tiez takto napadlo, ale mne ide o precvicovanie si funkcii. Vcera som totiz na funkcie a ich schopnost "rozdeluj a panuj" (rozdel si problem na male casti a ries ich postupne) natrafil. A dnes sa zamyslam nad tym, ze ako to pouzit.

rob

Re:funkcia v C - faktorial
« Odpověď #6 kdy: 15. 07. 2013, 11:50:53 »
tak to si naprogramuj funkci na serazeni posloupnosti celych cisel.
Pouzij algoritmus binarniho puleni a mas to procviceny :)

gamer

Re:funkcia v C - faktorial
« Odpověď #7 kdy: 15. 07. 2013, 12:00:00 »
Vilém: s rozdělováním faktoriálu na fukce jsi na dobré cestě, jednou z tebe bude enterprise programmer ;):
http://dis.4chan.org/read/prog/1180084983/

vilém

Re:Funkcia v C - faktorial
« Odpověď #8 kdy: 15. 07. 2013, 12:21:59 »
gamer: diky za povzbudenie. Moje snahy vsak vacsinou idu inym smerom Som po ukonceni studia na VS - odbor humanitnych vied - Anglicky a nemecky jazyk pre ZS a SS. Programovanie ma "dostalo" iba preto, lebo som pomahal bratrancovi rozpracovavat maturitne otazky z informatiky. Popri tom si zo mna robil zartiky, ze ovlada Pascal a HTML a PHP a ja nic. Tak ma to vytocilo a dnes som ho s vedomostami s programovania troska preskocil a hrajkam sa s funkciami. Napr. minuly tyzden to bolo nacitanie suboru a vykonanie nejakej operacie a ulozenie do ineho suboru.
Dalej zacinam tak troska s programovanim, aby si zo mna moji buduci ziaci neutahovali, ze oni vedia nieco, co ja nie. Od septembra (9. mesiac) zacinam totiz pracovat ako profesor AJ a NJ na priemyselnej skole elektrotechnickej.

gamer

Re:Funkcia v C - faktorial
« Odpověď #9 kdy: 15. 07. 2013, 12:32:00 »
Podle mě sis nezvolil dobrý jazyk do začátku, C je pro začátečníka dost hardcore (ale o tom je tady flamewar v jiném vlákně...). Zkus se podívat i na python:
http://wiki.python.org/moin/BeginnersGuide/

vilém

Re:Funkcia v C - faktorial
« Odpověď #10 kdy: 15. 07. 2013, 12:47:06 »
Ja viem, ze je to troska hardcore na zaciatok. Tiez mi odporucali Python. Najprv som zacal s Pythonom podla knizky Dive into Python 3 od Pilgrima. Avsak sposob jeho vysvetlovania bol pre mna nanajvys nevhodny. Okrem toho, mam prazdniny, cize vela casu.

Potom som vsak na nete natrafil na Ucebnicu jazyka C pre kvartu a kvintu 8-rocneho gymnazia od jedneho ucitela informatiky (Konkretne tu: http://www.smnd.sk/anino/moje/C.pdf) Tam bolo vsetko krasne vysvetlovane. Navyse tam boli aj cvicne ulohy - to prave orechove pre mna, aby som sa presvedcil, ze ci problematiku naozaj ovladam.
A kedze kvarta a kvinta su nejak 9. rocnik ZS/1. rocnik SŠ, tak som si povedal, ze to skusim.

Okrem toho, ako tak programujem, tak v C vidim zopar vyhod oproti Pythonu v tom, ze nepotrebujem po skompilovani kodu mat nejaky dodatocny interpreter ako v Pythone.

Okrem toho, este niektore odpovede na otazky hladam po nete a v knihe Jazyk C od Dalibora Kacmara.

gamer

Re:Funkcia v C - faktorial
« Odpověď #11 kdy: 15. 07. 2013, 13:00:38 »
Z té knížky bych vybral jen jeden příklad, aby bylo vidět, jak dokáže být C záludné:
Kód: [Vybrat]
float uradnik(float r)
{
    float s;
    s = 3.1415926 * r * r;
    return( s );
}
Většina lidí si myslí, že se to bude počítat jako float, ale není to tak. 3.1415926 je totiž datový typ double, takže všechny argumenty toho výrazu (r) se převedou na double, výpočet se provede v double a nakonec se výsledek opět převede na float. Konverze float <-> double jsou hodně drahé, takže ve výsledku to bude mnohem pomalejší, než kdyby bylo všechno v double. Správný zápis té konstanty má být 3.1415926f.

gcc pro 3.1415926 vygeneruje tenhle kód:
Kód: [Vybrat]
uradnik:
.LFB11:
    .cfi_startproc
    unpcklps    %xmm0, %xmm0
    cvtps2pd    %xmm0, %xmm1
    movsd   .LC0(%rip), %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    unpcklpd    %xmm0, %xmm0
    cvtpd2ps    %xmm0, %xmm0
    ret
a pro 3.1415926f:
Kód: [Vybrat]
uradnik:
.LFB11:
    .cfi_startproc
    movaps  %xmm0, %xmm1
    movss   .LC0(%rip), %xmm0
    mulss   %xmm1, %xmm0
    mulss   %xmm1, %xmm0
    ret

Karel

Re:Funkcia v C - faktorial
« Odpověď #12 kdy: 15. 07. 2013, 14:42:48 »
No, funkce otrok není zrovna dobrá jako příklad rozděl a panuj. Funkce, které zadám číslo a ona mi vrátí přesně to samé číslo. To je spíš metoda rozděl a panuj podle státní správy - když už není co dělit, tak se nějaká nová funkce vymyslí i když nic nedělá.

Doporučuji jednu věc, kterou "staří" programátoři ovládají poměrně dobře. Je to Desk Checking. Vemte si tužku, papír, a zkuste si ten program spustit "ručně". Prostě si ho odkrokujte tužkou na papír. Poměrně záhy tak objevíte zbytečnost funkce otrok a i vám bude jasné, proč výpis začíná nejvyšším číslem a klesá.

Programování není žádná alchymie. Obzvláště v C ne. Co v něm ale nefunguje je metoda pokus a omyl. Přepisovat + na -, vyměňovat for za while atd., tím se nikam nedostanete. V první řadě musíte pochopit, co vlastně chcete udělat. Pokud chcete vypsat čásla od 1 do N, tak vám musí být jasné, že začínáte u 1 a jdete nahodu. Začít na N a jít dolu těžko může produkovat požadovaný výsledek. I když i na to jsou triky, stačí vypsat zadanou hodnotu minus počitadlo, nebo to psát do pomocného řetězce zprava doleva.

A na závěr se přidávám k jednomu z diskutujících - zadaná úloha je natolik triviální, že na ni rozděl a panuj nelze efektivně použít. Tam prostě není co "delegovat", protože je tam výpočet jediný. Pomohlo by změnit trochu zadání - třebas aby se výpis prováděl rekurzivně.

rob

Re:Funkcia v C - faktorial
« Odpověď #13 kdy: 15. 07. 2013, 14:53:22 »
No ten assembler mu urcite pomuze :-D

Hele pokud chces zacit s ceckem, musis si nastudovat dost teorie. Jak jsou ulozeny v pameti jednotlivy dat. typy, staticky/dynamicka alokace, dal pamet na zasobniku/halde, pointry na dat. typy/fce a pripadne aritmetika s nima. Konverze mezi dat. typy; struktury,uniony atd atd

Segfaulty a mem leaky nebudu tady rozvadet vubec :-D

prezek

  • ***
  • 227
    • Zobrazit profil
Re:Funkcia v C - faktorial
« Odpověď #14 kdy: 15. 07. 2013, 16:28:01 »
Hele, pokud chceš začít s céčkem, tak hlavně nesmíš studovat moc teorie (pokud tě na tom nezajímá právě ta teorie). Vědomosti "jak jsou ulozeny v pameti jednotlivy dat. typy, staticky/dynamicka alokace, dal pamet na zasobniku/halde, pointry ..." ti budou v začátku na nic.
Já se programováním už pár let živím a stejně ještě pořád ani nechápu, jak program Hello World ve Windows, nebo Linuxu funguje. Snad to pochopím dřív, než půjdu do důchodu.

Dobré je naučit se krokovat program v debugeru a sledovat, co se děje, případně krokovat program na papíře, jak psal Karel.