2015-06-02 3 views
12

Ich bin einen Anfänger im Umgang mit Lambda Ausdruck Funktion in Java 8 Lambda-Ausdrücke bei der Lösung von Programmen wie Prime Nummernprüfung sehr gut geeignet ist, multifaktoriellen usw.Java 8 Lambda-Ausdrücke für Fibonacci Lösung (nicht rekursiv)

jedoch Können sie effektiv bei der Lösung von Problemen wie Fibonacci verwendet werden, wo der aktuelle Wert von der Summe der vorherigen zwei Werte abhängt. Ich habe ziemlich gut Primzahl-Check-Problem effektiv mit Lambda-Ausdrücke gelöst. Der Code für das gleiche ist unten angegeben.

boolean checkPrime=n>1 && LongStream.range(2, (long) Math.sqrt(n)).parallel().noneMatch(e->(n)%e==0); 

In dem obigen Code in der noneMatch Methode, die wir mit dem aktuellen Wert (e) im Bereich evaluieren. Aber für das Fibonacci-Problem benötigen wir zwei vorherige Werte.

Wie können wir es möglich machen?

Antwort

25

Die einfachste Lösung ist es, einen Strom von Pair s zu verwenden:

Stream.iterate(new long[]{ 1, 1 }, p->new long[]{ p[1], p[0]+p[1] }) 
     .limit(92).forEach(p->System.out.println(p[0])); 

Aufgrund des Fehlens eines Standard-Paartyp

, verwendet es ein Zwei-Element-Array. Außerdem verwende ich .limit(92), da wir nicht mehr Elemente mit long Werten auswerten können. Aber es ist leicht zu BigInteger anzupassen:

Stream.iterate(new BigInteger[]{ BigInteger.ONE, BigInteger.ONE }, 
       p->new BigInteger[]{ p[1], p[0].add(p[1]) }) 
     .forEach(p->System.out.println(p[0])); 

Das wird ausgeführt, bis Sie nicht genügend Speicher haben den nächsten Wert zu repräsentieren.

BTW, das n-te Element aus dem Strom zu erhalten:

Stream.iterate(new long[]{1, 1}, p -> new long[]{p[1], p[0] + p[1]}) 
    .limit(91).skip(90).findFirst().get()[1]; 
+0

Dank dieses Ansatzes funktioniert –

2

Lösung Fibonacci (nicht rekursiv)

Dies wird nicht mit Ihrem Ansatz

Die Erzeugung von Fibonacci-Zahlen basieren auf den beiden vorangegangenen Zahlen passieren wird auf der Grundlage der beiden vorangegangenen Zahlen, dh es ist ein rekursiver Algorithmus, auch wenn Sie es ohne Rekursion aber in einer Schleife implementieren.

Es gibt andere Möglichkeiten, die auf der Matrix Exponential basieren, so dass Sie die n-te Fibonacci-Zahl ohne Berechnung der n-1 vorherigen Zahlen berechnen können, aber für Ihr Problem (Berechnung der Serie) macht dies keinen Sinn.

Also, um Ihre Frage am Ende zu beantworten, nämlich Wie kann ich Lambda Ausdrücke auf den beiden vorherigen Elementen verwenden?: haben Sie eine Liste von Tupeln, die jeweils zwei aufeinanderfolgende Zahlen enthalten, und iterieren Sie darüber, indem Sie bei jedem Schritt ein neues Tupel hinzufügen.

1

Wenn Sie eine nicht rekursive Implementierung die n-te Zahl der Fibonacci-Folge finden können Sie die Formel verwenden:

Un = ((1+sqrt(5))^n - (1-sqrt(5))^n)/(2^n * sqrt(5)) 

Binet's Fibonacci Number Formula

long fibonacci(int n) { 
    return (long) ((Math.pow(1 + Math.sqrt(5), n) - Math.pow(1 - Math.sqrt(5), n))/
     (Math.pow(2, n) * Math.sqrt(5))); 
} 
+0

Der Java-Code ist nicht korrekt. Es sollte "Math.pow (1 + Math.sqrt (5), n)" nicht "1 + Math.pow (Math.sqrt (5), n)" neben anderen Problemen sein. – armandino

+1

In der Praxis wird dies aufgrund der begrenzten Fließkomma-Genauigkeit nur als Näherung für große n dienen. –

0

bis N-ten Fibonacci-Element (mit Reduktion) zu erhalten:

Stream.iterate(new long[] {1, 1}, f -> new long[] {f[1], f[0] + f[1]}) 
    .limit(n) 
    .reduce((a, b) -> b) 
    .get()[0];