Fakultät in logarithmischer Lauftzeit berechnen



  • tja siehst du, genau das Problem habe ich auch ... also angeblich soll das gehen, halt mit einem Trick ... aber da ich zur Zeit echt keinen Plan habe, wie der Trick aussehen soll, habe ich einfahc mal diesen Beitrag hier geschrieben ...

    vielleicht findet sich ja noch jemand, der eine Idee hat ...

    aber danke



  • Du könntest eine Lookup-Table lösung implementieren. Du codierst hart die Fakultäten für z.B. jeden 10. Integer ein, startest bei f[n % 10] aus deinem hartcodierten Array und machst von dort aus weiter. Dadurch kommst du je nach Höhe des n von der Laufzeit auf jeden Fall unter O(n) und O(log n). Der Nachteil ist, dass du die LUT immer an den Wertebereich des Ganzzahltyps anpassen musst.



  • Aber dadurch wird es vielleicht schneller, aber nicht logarithmisch... Ich bin immer noch der Meinung, dass die logarithmische Version O(log n) nicht möglich ist. O(n log(n)) dürfte doch die rekursive sein, oder?



  • also wie gesagt, mein erster Gedanke war auch,das geht nicht ... aber sicher bin ich mir nicht ... habe jetzt ne Woche Zeit, herauszufinden, ob oder ob nicht ...

    kann dir zu deinen letzen Ausführungen nur zustimmen ...

    mal sehen, was ich noch so in den nächsten Tagen rausfinde zu dem Prob ...



  • Ich würde alle Werte vorher berechnen und in eine Tabelle stecken. Das sind ja nicht so viele, weil der Wertebereich einer 32-Bit oder auch 64-Bit Ganzzahl einfach nicht so viel hergibt. Du hast dann zur Laufzeit O(1), was auch O(log(n)) ist, wenn du dir die Definition der O-Notation mal anschaust.



  • Du hast nicht zufällig einen Paralellrechner zur Verfügung? 😉



  • Du könntest vieleicht die Primfaktorzerlegung berechnen und die dann ausmultiplizieren. Für die Fakultät geht die Primfaktorzerlegung relativ schnell. Fragt sicht nur ob relativ schnell schnell genug ist... Ich vermute mal eher nicht.



  • Die Idee ist nicht schlecht ... aber denke auch, daß ist nicht die gesuchte Lösung ... werde es aber spasseshalber mal programmieren ...

    danke ...



  • Und, hat dein Prof mal gesagt, wie der Trick sein soll?



  • TGGC schrieb:

    Und, hat dein Prof mal gesagt, wie der Trick sein soll?

    Klar, am Wochenende 🙄 😃 .





  • also sehe meinen Prof wirklich nur sehr selten am We 😉 😃 ... aber werde es, wenn dann auch erst nächste Woche Freitag erfahren ... bis dahin habe ich Zeit ... und es wäre absolut genial, wenn ich das irgendwie hinkriegen würde ...



  • volkard schrieb:

    http://www.luschny.de/math/factorial/SrcJava/FactorialSimpleSwing.html

    Wie kann das logarithmische Laufzeit haben? Das for in swing() läuft doch mit O(n), weil die Schleife n Schritte macht. Zwar nicht auf einmal, aber insgesamt schon, da m ja nur im Schleifenkopf geändert wird.



  • TGGC schrieb:

    volkard schrieb:

    http://www.luschny.de/math/factorial/SrcJava/FactorialSimpleSwing.html

    Wie kann das logarithmische Laufzeit haben? Das for in swing() läuft doch mit O(n), weil die Schleife n Schritte macht. Zwar nicht auf einmal, aber insgesamt schon, da m ja nur im Schleifenkopf geändert wird.

    korrekt. hat lineare. dabei sah das so schnell aus.
    ich überleg morgen den ganzen tag, aber ich fürchte, da find ich nix.

    @CBR-Racer: was habt ihr gerade an vorlesungsstoff dran? vielleicht gibt das uns nen tip.



  • Ich weiß nun nicht genau, wie die Laufzeit berechnet wird. Ich denke mal, dass es die Anzahl der Multiplikationen in Abh. von n sind. Dann habe ich auf jeden Fall einen Algo gefunden, der die Fakultät in O(n/2) ausrechnet (wenn man das Multiplizieren mit 2 nicht mitrechnet 🙄 ). Es ist ja z.B.

    8! = 5 * ((5-1)(5+1)) * ((5-2)(5+2)) * ((5-3)(5+3))
       = 5 * (25-1²) * (25-2²) * (25-3²)
    

    Mit q = (n/2 + 1) gilt allgemein

    n! = q * (q²-1²) * (q²-2²) * ... * (q²-(q-2)²)
    

    Setzen wir nun
    ak=q2k2,a_k = q^2 - k^2,
    dann gilt
    ak+1=(q2k2)2k1=ak(2k+1).a_{k+1} = (q^2 - k^2) - 2k - 1 = a_k - (2k + 1).
    Wenn wir nun die Multiplikation mit 2 vernachlässigen, so können wir also ak+1 aus ak ohne Aufwand berechnen. Da nun
    n! = q \cdot a\_1 \cdot a\_2 \cdot \dots \cdot a_{q-2},
    haben wir
    q2=n2+12=n21q-2 = \frac{n}{2} + 1 - 2 = \frac{n}{2} - 1
    Multiplikationen.

    EDIT: Bei ungeradem n kommt noch eine Multiplikation mit n dazu.



  • WebFritzi schrieb:

    Ich weiß nun nicht genau, wie die Laufzeit berechnet wird. Ich denke mal, dass es die Anzahl der Multiplikationen in Abh. von n sind. Dann habe ich auf jeden Fall einen Algo gefunden, der die Fakultät in O(n/2) ausrechnet (wenn man das Multiplizieren mit 2 nicht mitrechnet 🙄 ).

    Bin jetzt zu muede, die genaue Definition nachzuschlagen, aber auf jedenfall ist O(n/2) = O(n). Und damit sind wir wieder am Anfang.



  • SG1 schrieb:

    Bin jetzt zu muede, die genaue Definition nachzuschlagen, aber auf jedenfall ist O(n/2) = O(n). Und damit sind wir wieder am Anfang.

    Na jut, dann ist das wohl diese lineare Geschichte.
    O(n)={f:NRa,bRmitf(n)=an+b}O(n) = \{f: \mathbf{N}\to\mathbf{R}\,|\, \exists a,b\in\mathbf{R}\;mit\; f(n) = an + b\}



  • Ich weiß garnicht, warum hier jeder irgendwas kompliziertes berechnen will. Es ist vollkommen legitim und natürlich, bei einer Funktion, die nur für etwa 20 Werte sinnvolle Ergebnisse liefert, die Ergebnisse einfach direkt in den Quellcode zu schreiben. Schreib sie in ein Array, dann kriegst du O(1), wenn dir das zu schnell ist und du nichts schnelleres als O(log(n)) haben möchtest (wobei O(1) eigentlich in O(log(n)) liegt), dann schreib sie halt in nen Baum und such sie dir mit binärer Suche raus. 😉

    Oder sollt ihr die Funktion für einen Datentyp schreiben, der ein paar hundert Stellen lange Zahlen erlaubt?



  • WebFritzi schrieb:

    SG1 schrieb:

    Bin jetzt zu muede, die genaue Definition nachzuschlagen, aber auf jedenfall ist O(n/2) = O(n). Und damit sind wir wieder am Anfang.

    Na jut, dann ist das wohl diese lineare Geschichte.
    O(n)={f:NRa,bRmitf(n)=an+b}O(n) = \{f: \mathbf{N}\to\mathbf{R}\,|\, \exists a,b\in\mathbf{R}\;mit\; f(n) = an + b\}

    Deine Definition ist falsch. Die O-Notation ist wie folgt definiert:

    O(g(n)) = {f:N->R | Es gibt ein c aus R+ und es gibt ein n0 aus N, so dass für alle n >= n0 gilt: |f(n)| <= c|g(n)|}



  • Na gut. Ist ja so ähnlich. Also
    O(n)={f:NRa,bR+mitf(n)an+b}O(n) = \{f: \mathbf{N}\to\mathbf{R}\,|\, \exists a,b\in\mathbf{R}^+\;mit\; |f(n)| \le an + b\}


Anmelden zum Antworten