Fakultätsoperator für ein Programm?



  • Will ein Programm schrieben das mit einen Fakultätsoperator rechnen kann. Nur es gibt eine Problem ich weiß nicht wie der Fakultätsoperator rechnet, nur so viel das (7! = 7*6*5*4*3*2*1). Durch die Recherche habe eine Vorstellung wie der Code aussehen könnte:

    int fakultaet(int zahl)
    {
        int ergebnis = 1;
    
        for (int i=2;i<=zahl;i++)
        {
            ergebnis = ergebnis * i;
        }    
    
        return ergebnis;
    }
    

    Oder

    (define (fact n)
      (if (= n 1)
          1
          (* n (fact (- n 1)))))
    

    Oder

    double fak( double x) {
    if(x>=1)
    return 1
    return fak( x-1);
    }
    


  • #include <iostream> 
    
    template <int N> 
    class fakultaet 
    { 
      public: 
        enum { value = N * fakultaet<N - 1>::value }; 
    }; 
    
    template <> 
    class fakultaet<1> 
    { 
      public: 
        enum { value = 1 }; 
    }; 
    
    int main() 
    { 
      std::cout << fakultaet<4>::value << std::endl; 
    }
    

  • Mod

    Und deine Frage?

    Das eine ist übrigens kein C++. Lisp?



  • Du kannst in C++ keine Willkürlichen Zeichen als Operatoren definieren. Das geht nur in wenigen Sprachen (z.Bsp. Perl 6).
    Deine jetzige Implementation ist relativ langsam und wenn du die Zahlen, die du verwenden willst schon zur Kompillierzeit weisst, würde ich dir Boost.Math.Factorial empfehlen.

    Im Code steht dann:

    #include <boost/math/special_functions/factorials.hpp>
    int fact10 = boost::math::factorial(10);
    
    // oder
    #include <boost/math/special_functions/factorials.hpp>
    using namespace boost::math;
    int fact10 = factorial(10);
    


  • SeppJ schrieb:

    Das eine ist übrigens kein C++. Lisp?

    Scheme.
    Und das dritte ist syntaktisch falsch und ansonsten eine recht umständliche Art und Weise, return 1; zu schreiben, aber keine Fakultät 🙂 Das erste sieht doch ganz gut aus, wo ist das Problem?



  • kurz und knapp:

    int fak(int n) { return (n<2) ? n : n * fak(n-1); }
    

    rekursive definition und sehr kurz geschrieben 😉



  • TheQ schrieb:

    kurz und knapp:

    int fak(int n) { return (n<2) ? n : n * fak(n-1); }
    

    rekursive definition und sehr kurz geschrieben 😉

    und falsch.



  • Danke für die Hilfe, jetzt kann ich es im den Code infügen.



  • Bashar schrieb:

    TheQ schrieb:

    kurz und knapp:

    int fak(int n) { return (n<2) ? n : n * fak(n-1); }
    

    rekursive definition und sehr kurz geschrieben 😉

    und falsch.

    wo denn?


  • Mod

    TheQ schrieb:

    Bashar schrieb:

    TheQ schrieb:

    kurz und knapp:

    int fak(int n) { return (n<2) ? n : n * fak(n-1); }
    

    rekursive definition und sehr kurz geschrieben 😉

    und falsch.

    wo denn?

    Gib mal 0 ein.



  • ok, mal laut wikipedia die definition angeschaut und verbessert.

    int fak(int n) { return (n==0) ? 1 : n * fak(n-1); }
    


  • sieht richtig aus.


  • Mod

    Ist aber immer noch ziemlich lahm. Für Fakultäten gibt es keinen guten Grund zur Rekursion zu greifen. Schließlich gibt es keinerlei Verzweigungen im Ablauf.



  • Bei dir kann man -1 eingeben und das Resultat ist sicher komisch.
    Deshalb:

    // 1. Variante
    unsigned fak(unsigned n) { return n?n*fak(n-1):1; }
    // 2. Variante
    int fak(int n) { return n<2?1:n*fak(n-1); } // 1 bei -1 ist zwar komisch, aber verständlich
    


  • Des halb habe ich auch aus Performancegründen zum TMP gegriffen ^^



  • Ja sicher, TMP: überhaupt nicht rekursiv und sehr schnell und praxisbezogen:

    int i;
    std::cin >> i;
    std::cout << fakultaet<i>() << std::endl;
    

    Da verwende ich doch lieber Boost, weil für vordefinierte Werte Fakultäten vom Compiler berechnen zu lassen ist doch eher unüblich (und ausserdem musst du die Funktion sehr oft aufrufen, um die dafür zusätzlich benötigte Compilezeit wieder reinzuholen).


  • Mod

    int fak(unsigned n)
    {
      unsigned result=1;
      for (unsigned i=1; i<=n; ++n) result*=i;
      return result;
    }
    

    Sieht zwar weniger schick aus, aber lasst das mal gegen die Rekursionsfunktion rennen.

    edit: <= natürlich. Alte Gewohnheit 🙂



  • SeppJ schrieb:

    int fak(unsigned n)
    {
      unsigned result=1;
      for (unsigned i=1; i<=n; ++n) result*=i;
      return result;
    }
    

    Sieht zwar weniger schick aus, aber lasst das mal gegen die Rekursionsfunktion rennen.

    edit: <= natürlich. Alte Gewohnheit 🙂

    Ist aber immernoch falsch 😉



  • hmmmmm,..

    x>(2^13) kommt doch so oder so ein überlauf,... da beschwer ich mich doch nicht über die performance,... geschweige das das double noch net mal darstellen kann,..

    greetz



  • HighLigerBiMBam schrieb:

    Ist aber immernoch falsch 😉

    template<typename Type>
    Type Facul(Type x) {
    	if(x<0) return 0;
    	Type f=1;
    	while(x>1) f*=x--;
    	return(f);
    }
    

    So kann's aussehen. Von rekursiven Aufrufen kann ich nur abraten, bei solchen Spielfunktonen noch akzeptabel, ist bei einigen anderen Algorithmen wie z.B. Floodfill nicht angebracht.


Anmelden zum Antworten