Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
private static ArrayList<BigInteger> fibCache = new ArrayList<BigInteger>();
static {
fibCache.add(BigInteger.ZERO);
fibCache.add(BigInteger.ONE);
}
public static BigInteger fib(int n) {
if (n >= fibCache.size()) {
fibCache.add(n, fib(n-1).add(fib(n-2)));
}
return fibCache.get(n);
}
Diese Methode ist wesentlich schneller, da sie die Vorgängerwerte nicht jedesmal neu berechnet. Nachteil ist allerdings, dass ab einer gewissen Fibonacci Zahl ( bei mir ca. f(1000000)) der schon auf 1,6 gb vergrößerte Java Heap Space überläuft.
Ein weiterer in Python geschriebener Algorithmus der sehr schnell sein soll ist hier zu finden: http://krenzel.info/?p=85
Den bekomm ich aber nicht nach Java portiert. Kann mir da jemand helfen?
Insgesamt meine Frage an euch: Kennt jemand einen schnelleres Verfahren zur Berechnung der Fibonacci Zahlen als die beiden oben genannten?
Hat jemand Verbesserungsvorschläge zu den oben genannten Algorithmen?
> Nachteil ist allerdings, dass ab einer gewissen Fibonacci Zahl ( bei mir ca. f(1000000)) der schon auf 1,6 gb vergrößerte Java Heap Space überläuft.
vielleicht beide Verfahren kombinieren:
nur jede 1000te Zahl speichern bzw. zwei je hintereinander liegende,
senkt den Speicherbedarf auf 1.6 mb und die Berechnung ist immer noch 1000 mal schneller (statt 1000x1000 mal)
je größer die Zahlen, desto größer der Abstand bei der Speicherung und desto langsamer das Verfahren, falls verkraftbar
sofern es in diesem Fall eine fertige Formel gibt, ist das natürlich eher eine theoretische Überlegung
Wenn es nur um die Berechnung einer einzelnen Fibonacci-Zahl geht, dürfte folgendes am schnellsten sein:
Code:
public static BigInteger fibonacci(int n)
{
BigInteger a = new BigInteger("0");
BigInteger b = new BigInteger("1");
while (--n > 0)
{
BigInteger c = a.add(b);
a = b;
b = c;
}
return b;
}
Und wenn Du die ersten n Fibonacci-Zahlen ausgeben willst, bau das println einfach mit ein:
Code:
public static void printFirstFibonacciNumbers(int n)
{
BigInteger a = new BigInteger("0");
BigInteger b = new BigInteger("1");
while (--n >= 0)
{
System.out.println(b);
BigInteger c = a.add(b);
a = b;
b = c;
}
}
Falls Du allerdings völlig willkürlich irgendwelche Fibonacci-Zahlen berechnen willst (also keine Sequenz), dann fällt mir da auf Anhieb gerade nix vernünftiges ein.
Das ist laaange nicht die schnellste Methode. Es gibt dutzende Formeln zum "Abkürzen", etwa
F(2n) = F(n+1)^2 - F(n-1)^2
Habe mal das Programm aus "Algorithmische Zahlentheorie" von Prof. O. Forster abgetippt, das solche Tricks benutzt. Schätze mal dagegen ist deine Variante lahm wie eine amputierte Ente...
Code:
private final static BigInteger TWO = BigInteger.valueOf(2);
public static BigInteger fib(int value) {
BigInteger n = BigInteger.valueOf(value);
if (n.compareTo(BigInteger.ONE) <= 0) {
return n;
}
BigInteger x = BigInteger.ONE;
BigInteger y = BigInteger.ZERO;
for (int k = n.bitLength() - 2; k >= 0; k--) {
BigInteger xx = x.pow(2);
x = xx.add(TWO.multiply(x).multiply(y));
y = xx.add(y.pow(2));
if (n.testBit(k)) {
BigInteger temp = x;
x = x.add(y);
y = temp;
}
}
return x;
}
Das ist laaange nicht die schnellste Methode. Es gibt dutzende Formeln zum "Abkürzen", etwa
F(2n) = F(n+1)^2 - F(n-1)^2
Habe mal das Programm aus "Algorithmische Zahlentheorie" von Prof. O. Forster abgetippt, das solche Tricks benutzt. Schätze mal dagegen ist deine Variante lahm wie eine amputierte Ente...
Code:
private final static BigInteger TWO = BigInteger.valueOf(2);
public static BigInteger fib(int value) {
BigInteger n = BigInteger.valueOf(value);
if (n.compareTo(BigInteger.ONE) <= 0) {
return n;
}
BigInteger x = BigInteger.ONE;
BigInteger y = BigInteger.ZERO;
for (int k = n.bitLength() - 2; k >= 0; k--) {
BigInteger xx = x.pow(2);
x = xx.add(TWO.multiply(x).multiply(y));
y = xx.add(y.pow(2));
if (n.testBit(k)) {
BigInteger temp = x;
x = x.add(y);
y = temp;
}
}
return x;
}
Stimmt! Der Algorithmus ist wesentlich schneller. Leider verstehe ich nicht warum das funktioniert. Kann ich mir auch jede dazwischenliegende Fibonacci Zahl ausgeben lassen?
der Algorithmus ist gerade deswegen so schnell, weil so viele Zahlen übersprungen werden,
um die dazwischenliegenden auszugeben müsstest man die ja alle berechen,
das ist ein Widerspruch
warum F(2n) = F(n+1)^2 - F(n-1)^2 gilt steht auf irgendwelchen Seiten wie vielleicht Wikipedia als Beweis,
das muss man einmal durchrechnen, kann man nicht durch Anschauen 'verstehen'
edit: das angegebene Programm ist wohl noch ein anderes
Wenn du natürlich *alle* Zahlen ausgeben willst, ist die normale Berechnung natürlich OK, aber das war oben nicht gefragt. Habe nicht getestet, wie schnell es ist. Die Zeit für F(10000) war jedenfalls kaum meßbar.
Der Algorithmus verwendet zwei andere Formeln (eine für F(2n) und eine für F(2n+1)). Finden sich u.a. auf http://www.ijon.de/mathe/fibonacci/node2.html . Im Prinzip kann man die ganzen Fibo-Formeln einfach durch Einsetzen in die Binet-Formel beweisen, aber natürlich ist der Beweis "zu Fuß" interessanter...
Das Programm unter dem oben angegebenen Link (http://krenzel.info/?p=85) scheint übrigens so ähnlich wie meins zu arbeiten.
Da es auch eine Formel für F(3n) gibt, ist das Ende der Fahnenstange wohl noch nicht erreicht...
Übrigens gibt es einen einfachen Test, um festzustellen, ob eine gegebene Zahl eine Fibonacci-Zahl ist:
n ist eine Fibonacci-Zahl genau dann wenn entweder 5n²+4 oder 5n²-4 eine Quadratzahl ist (Gessel, 1972)