Übungsaufgabe Fakultät

Hallo! Ich sitze gerade vor einer JAVA -Anfänger-Aufgabe und weiß nicht weiter:

Schreiben Sie ein Programm, welches das Ergebnis folgender Formel berechnet: n! = n(n-1)! Mit welchem “Werkzeug” der Programmiersprache Java lässt sich diese Aufgabe lösen.*

Ich hoffe mir kann hier jemand helfen…

Besten Dank schonmal

Hast du schon einen Ansatz für die Aufgabe?

Falls nicht:
Wenn du dir den Term genau anschaust, siehst du, dass die Funktion “!” (Fakultät) rekursiv definiert ist.
Um die Funktion auszurechnen, musst du sie wieder verwenden (auf n-1).

Für jede Rekursive Funktion braucht es immer eine Abbruchbedingung/Rekursionsanker, in dem Fall dürfte das 0! = 1 sein.
Das ganze kann man dann etwa in der Form hinschreiben (Pseudocode):

if(Bedingung von Rekursionsanker erfüllt){
return Wert von Rekursionsanker;
}else{
recursiveFunction(veränderter Parameter);
}
}```

n! = n*(n-1)!

n! ist doch ein klassischer Funktionsaufruf. Wie z.b. 7!. Und dieser sieht in Java so aus

//bzw.
fakultaet(7);```

Also braucht es eine Funktion, die vielleicht ein Ergebnis liefert. Die Funktionssignatur könnte also so aussehen.
```static int fakultaet(int n)```

Jetzt braucht man sich nur noch daran machen diese mit Leben zu füllen.
```static int fakultaet(int n) {
  return n * fakultaet(n-1);
}```

Und damit das ganze Funktioniert braucht es noch einen Rekursionsanker. Das ist ein Spezialfall, bei dem nicht die übliche Prozedur verwendet werden soll, sondern z.B. ein Definierter Wert zurückgegeben wird. Bei der Fakultätsberechnung könnte dies der Fall für n <= 1 sein, bei dem 1 zurückgegeben wird.

```static int fakultaet(int n) {
  if(n <= 1) {
    return 1;
  } else {
    return n * fakultaet(n-1);
  }
}```

Ich glaube mit Vorkauen hilfst du dem TO nicht. Da war keinerlei Eigeninitiative erkennbar, und noch nicht einmal, was sein Problem mit der Aufgabe ist. Vor allem wird kein Leerkörper eine Aufgabe einfach so stellen, nach dem Motto “sollen sie halt zusehen, wie sie das lösen”. Morgen postet der TO die nächste Aufgabe und übermorgen weiß er dann in der Prüfung nicht weiter…

Vielen lieben Dank!

ich hab ernsthaft überlegt, die fakultät ohne Rekursion (Lambda) und ohne Schleife lösen zu wollen, aber nach einen Blick in Wikiped. ist klar, es werden (ungefähr) n-1 Multiplikationen benötigt. Aber das ist hier nicht wichtig, wichtig ist, welcher Datentyp eigentlich verwendet werden soll, int könnte irgendwann nicht mehr ausreichen, die fakultät ist eine schnellwachsende Funktion. Wir hatten mal gelernt, mit nur einer zweistelligen fAkultät lassen sich alle Atome des Universums fassen. In JAVA lassen sich das zwar in wenigen Zeilen schreiben, dennoch halte ich eine andere Programmiersprache für besser. @BOO : Bei Fragen einfach fragen, irgendwie hat immer jemand Zeit, zu antworten. Alles Wichtige (Zugriffsmodifier, Rückgabetyp, Name, Parametertyp, etc.), das wurde ja schon genannt.

Sorry, @CyborgBeta : Kannst Du bitte deine Texte irgentwie strukturieren?

Das zu lesen ist echt schmerzhaft. Zumal sehe ich auch nicht die direkte relevanz zur Frage des TO.

Und ja, ich bekomme Briefe. Ich möchte auch keine Diskussion lostreten, nimm es bitte einfach so zur Kentniss ;D

Das er Threads kapert ist doch nichts neues, war beim letzten Thread mit den Baum-Mustern doch genau so :rolleyes:.

[QUOTE=Unregistered]Die Funktionssignatur könnte also so aussehen.
static int fakultaet(int n)[/QUOTE]

Sorry Buddy, wer auch immer du bist, aber deiner Antwort entnehme ich das du ungefähr über den selben Kenntnisstand wie TO verfügst, denn : STATIC is EVIL !
Es gab schon sehr viele Diskusionen darüber wann static Sinn macht und wann nicht, und bei einer einfach Übungsaufgabe wird es wohl schon sicher ausreichen einfach mal static zu nutzen um dierekt von main() aus drauf zuzugreifen, aber Java ist eine objekt-orientierte Sprache. Es sollte also immer mit Objekten gearbeitet werden, egal wie einfach die Aufgabe auch ist. Und objekt-orientiertes Programmieren und das Keyword static passen irgendwie nicht zusammen.

Von daher also : “könnte so aussehen” > ok, sollte sie aber nicht.

Static fields sind ein Problem, solange es nicht Konstanten sind. Aber static methods sind OK. Dass jemand bei der Fakultätsfunktion polymorphes verhalten will, ist eher unwahrscheinlich. Abgesehen davon ist es eine Utility-Methode … wie z.B. alle (statischen!) Methoden in Math.

@Marc i und FP: Wollt ihr helfen - oder nur über die lästern, die tatsächlich helfen? Etwas mehr Struktur in dem kleinen Absatz ist auch unwichtig. Meine Antwort bezieht sich direkt auf die Frage des TE/TO, eine Überlegung, welcher Datentyp wenigstens für ein paar Fakultät en Sinn ergibt, ist KEIN Kapern des Threads. Btw.: Er kann es ja einfach einmal ohne static und einmal mit static schreiben.

Ich habe Dir kuz einmal aufgeschrieben, wie man das “profesionell” machen würde:

 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author CB
 */
public class Fak {

    private List<BigInteger> faks = new ArrayList<BigInteger>(Arrays.asList(BigInteger.ONE));

    public Number[] fak(final int n) { // < 0 prüfen?
        while (faks.size() - 1 < n) {
            faks.add(faks.get(faks.size() - 1).multiply(BigInteger.valueOf(faks.size())));
        }
        double doubleResult = 1;
        for (int i = 2; i <= n; i++) {
            doubleResult *= i;
        }
        return new Number[]{faks.get(n), doubleResult};
    }

    public static void main(String[] args) {
        Fak f = new Fak();
        for (int i = 0; i < 20; i++) {
            System.out.printf("% 15d% 15f%n", f.fak(i)); // oder % ... e/f/g
        }
    }
}```


Ausgabe:
[spoiler]

run:
1 1,000000
1 1,000000
2 2,000000
6 6,000000
24 24,000000
120 120,000000
720 720,000000
5040 5040,000000
40320 40320,000000
362880 362880,000000
3628800 3628800,000000
39916800 39916800,000000
479001600 479001600,000000
6227020800 6227020800,000000
87178291200 87178291200,000000
1307674368000 1307674368000,000000
20922789888000 20922789888000,000000
355687428096000 355687428096000,000000
6402373705728000 6402373705728000,000000
121645100408832000 121645100408832000,000000
BUILD SUCCESSFUL (total time: 0 seconds)

[/spoiler]


Es ist erschreckend, wie genau double schon bei solchen Dingen ist.

Grüße

Über den Begriff “professioneller” kann man sicherlich gut diskutieren :reflect:.

Als recht brauchbare Lösung würde ich die Implementierung aus Apache Commons, MathUtils anschauen:
(Relevante Stellen bei Zeile 78, 827 und 852)
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.commons/commons-math/2.2/org/apache/commons/math/util/MathUtils.java

Grundidee bei der Implementierung ist, die ersten Werte im Long-Bereich in einem Lookup-Array vorzuhalten (hartcodiert, keine Berechnungen nötig).
Werden höhere Werte benötigt (n > 21), wird das Ergebnis als Double berechnet und die Formel
n! = e^log(n!) verwendet.

Das hat den Vorteil, das man log(n!) als log(1) + log(2) + log(3) + … + log(n) schreiben kann.
Dadurch kommt man unter anderem auch ohne die BigInteger-Berechnungen aus, da der Wertebereich kleiner wird.
(Und kann noch andere Spielereien bei den log-Berechnungen einbauen, so tief bin ich aber nicht mehr eingestiegen).

Bzgl Thread kapern: Dem TO dürfte alles ab #5 eh egal sein, der Rest steht hier nur noch für andere Leute, die über den Thread stolpern :rolleyes:

Danke, für die Verlinkung, ich stecke mathematisch da nicht drin, ich weiß auch nicht, welchen Nutzen eine (riesige) fakultätszahl hätte. Für double ist alles ab dem Wert mit ungefähr e+306 zu klein. Aber ich freue mich, das auch dazu entschlossen wurde, bei Schleifenzählvariablenwert 2 anzufangen. :slight_smile:

*** Edit ***

Zur Rechtschreibung (kurz): Eh, zu groß und sich. Außerdem: Schleifen, Schleifenzähler, Schleifenzählervariable, dem Schleifenzählervariablewert 2. Ich hab’ 'was gefolgert. :slight_smile: Und die "Fugenlaut"e s, n, e usw. aber die kann auch keiner, deshalb sin unwischtig.

Schleifenzähl(er)variableninitialwert 2. :slight_smile:

z.B. in der Wahrscheinlichkeitsrechnung / Kombinatorik kommen Fakultäten sehr oft vor und definitiv auch mit höherem n als 21

Ja, aber soweit ich weiß, gibt es keine Wahrscheinlichkeit mit 1 zu 300! (die Werte werden so groß, dass das Ereignis a) nicht mehr eintritt und b) die Zahl keine Aussage mehr darstellt), Beispiel: 300 Karten werden echt wirklich zufällig und komplett gemischt, es wird einfach nicht davon ausgegangen, alle Karten in der richtigen Reihenfolge zu ziehen, spätestens nach 15 Karten, würden alle sagen, dass Spiel ist manipuliert, und den tisch verlassen…

Ich habe Dir kuz einmal aufgeschrieben, wie man das “profesionell” machen würde:

Wo?

Unglaublich: der TO stellt eine Anfängerfrage - und das Ergebnis ist dieser Thread. Warum muss CyborgBeta da seinen Müll reinschreiben, er kann doch nicht ernsthaft glauben dass er mit seinen tollen Sachen jemand beeindruckt? Und helfen tut das einem Anfänger auch nicht.

Guten Morgen, ja ne, ich wollte ein bisschen “angeben”. double rechnet (Multiplikation) wahrscheinlich etwas schneller als als BigInteger (auch Multiplikation). Anmerkung, erst mal alle Faks, die in ein long passen, zu speichern - oder einen passenden Konstruktor hinzuzufügen, wäre wahrscheinlich sinnvoll. log(n!) kleinere Werte, aber nicht so genau (mehr Rechenaufwand). Ginge auch Sqrt(n!)=sqrt(1)+sqrt(2)+…+sqrt(n-1)+sqrt(n) oder ist das Quatsch? Bitte nicht wieder ein eigenes Thema daraus abspalten. Es geht immer noch um Faks und rekursive Definition und Algos, das zu implementieren. Ich bin erst mal aus diesem Thema raus, was ich “weiß”, das wird nicht unbedingt benötigt.

Wie wärs statt mit nem eigenen thread, direkt mit einem eigenen Unterforum. Titel “Performance Precision Extrem Problem Solutions”