用于求解斐波那契的 Java 8 Lambda 表达式(非递归方式)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30595844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 Lambda expressions for solving fibonacci (non recursive way)
提问by Kiran Muralee
I am a beginner in using Lambda expression feature in Java 8. Lambda expressions are pretty well useful in solving programs like Prime number check, factorial etc.
我是在 Java 8 中使用 Lambda 表达式功能的初学者。 Lambda 表达式在解决诸如质数检查、阶乘等程序时非常有用。
However can they be utilized effectively in solving problems like Fibonacci where the current value depends on sum of previous two values. I have pretty well solved prime number check problem effectively using Lambda expressions. The code for the same is given below.
然而,它们能否有效地用于解决像斐波那契这样的问题,其中当前值取决于前两个值的总和。我已经很好地使用 Lambda 表达式有效地解决了素数检查问题。下面给出了相同的代码。
boolean checkPrime=n>1 && LongStream.range(2, (long) Math.sqrt(n)).parallel().noneMatch(e->(n)%e==0);
In the above code in the noneMatch
method we are evaluating with the current value(e
) in the range. But for the Fibonacci problem, we requires previous two values.
在方法中的上述代码中,noneMatch
我们使用e
范围内的当前值()进行评估。但是对于斐波那契问题,我们需要前两个值。
How can we make it happen?
我们怎样才能让它发生?
回答by Holger
The simplest solution is to use a stream of Pair
s:
最简单的解决方案是使用Pair
s流:
Stream.iterate(new long[]{ 1, 1 }, p->new long[]{ p[1], p[0]+p[1] })
.limit(92).forEach(p->System.out.println(p[0]));
Due to the lack of a standard pair type, it uses a two-element array. Further, I use .limit(92)
as we can't evaluate more elements using long
values. But it's easy to adapt to BigInteger
:
由于缺少标准对类型,它使用二元素数组。此外,我使用.limit(92)
因为我们无法使用long
值评估更多元素。但它很容易适应BigInteger
:
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]));
That'll run until you haven't enough memory to represent the next value.
这将一直运行,直到您没有足够的内存来表示下一个值。
BTW, to get the nth element from the stream:
顺便说一句,从流中获取第 n 个元素:
Stream.iterate(new long[]{1, 1}, p -> new long[]{p[1], p[0] + p[1]})
.limit(91).skip(90).findFirst().get()[1];
回答by elyor
To get Nth fibonacci element (using reduction):
要获得第 N 个斐波那契元素(使用归约):
Stream.iterate(new long[] {1, 1}, f -> new long[] {f[1], f[0] + f[1]})
.limit(n)
.reduce((a, b) -> b)
.get()[0];
Here is what is going on:
这是发生了什么:
Stream.iterate()- is producing pairs of numbers, each containing 2 consecutive elements of fibonacci. We have to use pairs, because we can access only the last element via "iterate", not 2 or more previous elements, so to generate a new pair, we get the last pair, which already contains 2 previous elements of fibonacci, and produce the next pair. And to get the Kth fibonacci element, we just need to get the left value from the Kth pair.
.limit(n)- to keep the first N pairs, and exclude the rest.
.reduce((a, b) -> b)- to get the last pair from the stream of N pairs from previous step.
.get()[0]- extract fibonacci element from the pair (left value of the pair)
Stream.iterate()- 生成成对的数字,每个数字包含 2 个连续的斐波那契元素。我们必须使用对,因为我们只能通过“迭代”访问最后一个元素,而不是 2 个或更多以前的元素,所以要生成一个新对,我们得到最后一对,它已经包含了斐波那契的 2 个以前的元素,并产生下一对。为了获得第 K 个斐波那契元素,我们只需要从第 K 个对中获得左边的值。
.limit(n)- 保留前 N 对,排除其余的。
.reduce((a, b) -> b)- 从上一步的 N 对流中获取最后一对。
.get()[0]- 从对中提取斐波那契元素(对的左值)
回答by Marcus Müller
solving fibonacci (non recursive way)
解决斐波那契(非递归方式)
This is not going to happen with your approach
你的方法不会发生这种情况
The generation of Fibonacci numbers based on the previous two numbers is based on the previous two numbers, i.e. it's a recursive algorithm, even if you implement it without recursion but in a loop.
基于前两个数字的斐波那契数的生成是基于前两个数字的,即它是一个递归算法,即使您没有递归而是在循环中实现它。
There's other ways based on the matrix exponential so you can calculate the n'th fibonacci number without calculating the n-1 previous numbers, but for your problem (calculating the series), this doesn't make sense.
还有其他基于矩阵指数的方法,因此您可以计算第 n 个斐波那契数而不计算 n-1 个先前的数字,但是对于您的问题(计算系列),这没有意义。
So, to answer your question in the end, namely how can I use Lambda expressions on the two previous elements?: have a list of tuples, each containing two consecutive numbers, and iterate over that, adding a new tuple every step.
那么,最后回答你的问题,即我如何在前两个元素上使用 Lambda 表达式?: 有一个元组列表,每个元组包含两个连续的数字,并迭代它,每一步添加一个新元组。
回答by Rodolfo
If you want a non recursive implementation to find the n-th number of Fibonacci sequence you can use the formula:
如果您想要一个非递归实现来找到第 n 个斐波那契数列,您可以使用以下公式:
Un = ( (1+sqrt(5))^n - (1-sqrt(5))^n ) / (2^n * sqrt(5))
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)));
}
回答by ICanHasNick
You can use a variable in your lambda expression to temporarily store the previous element, which is needed to calculate the next element in the fibonacci sequence.
您可以在 lambda 表达式中使用变量来临时存储前一个元素,这是计算斐波那契数列中的下一个元素所必需的。
public class FibonacciGenerator {
private long prev=0;
public void printSequence(int elements) {
LongStream.iterate(1, n -> {n+=prev; prev=n-prev; return n;}).
limit(elements).forEach(System.out::println);
}
}
Normally the method and the field would rather be declared as static but I wanted to show that instance fields can be used as well.
通常,方法和字段宁愿声明为静态,但我想表明也可以使用实例字段。
Please note that you could not use a local variable ( declared in a method or passed to a method ) instead of a field, for such variables need to be final in order to use them in lambdas. For our purpose we needed a mutable variable to store the different values during the iteration.
请注意,您不能使用局部变量(在方法中声明或传递给方法)而不是字段,因为此类变量需要是 final 才能在 lambda 中使用它们。出于我们的目的,我们需要一个可变变量来存储迭代期间的不同值。