使用 Java 8 IntStream 计算阶乘?
calculating factorial using Java 8 IntStream?
我在 Java 8 和 lambda 表达式以及 Stream
方面相对较新,我可以使用 for
循环或递归计算阶乘。但是有没有办法使用 IntStream
来计算一个数的阶乘呢?即使在整数范围内使用阶乘我也很好。
我在这里通读了 IntStream
文档,http://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html 我可以看到很多方法,但不确定我可以使用哪一种来计算阶乘。
例如,rang
方法说,
range(int startInclusive, int endExclusive) Returns a sequential
ordered IntStream from startInclusive (inclusive) to endExclusive
(exclusive) by an incremental step of 1.
所以我可以用它来为 IntStream 提供数字范围,乘以计算阶乘。
number = 5;
IntStream.range(1, number)
但是如何将这些数字相乘得到阶乘?
您可以使用 IntStream::reduce 完成这项工作,
int number = 5;
IntStream.rangeClosed(2, number).reduce(1, (x, y) -> x * y)
要获得所有无限阶乘的流,您可以这样做:
class Pair{
final int num;
final int value;
Pair(int num, int value) {
this.num = num;
this.value = value;
}
}
Stream<Pair> allFactorials = Stream.iterate(new Pair(1,1),
x -> new Pair(x.num+1, x.value * (x.num+1)));
allFactorials
是数字的阶乘流,从 1 到 ..... 要获得 1 到 10 的阶乘:
allFactorials.limit(10).forEach(x -> System.out.print(x.value+", "));
它打印:
1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
现在假设您只希望得到特定数字的阶乘,然后执行:
allFactorials.limit(number).reduce((previous, current) -> current).get()
最好的部分是您不需要为新数字重新计算,而是建立在历史的基础上。
使用 LongStream.range() 您可以计算小于 20 的数字的阶乘。如果您需要计算更大的数字,请使用 BigInteger 创建流:
public BigInteger factorial(int number) {
if (number < 20) {
return BigInteger.valueOf(
LongStream.range(1, number + 1).reduce((previous, current) -> previous * current).getAsLong()
);
} else {
BigInteger result = factorial(19);
return result.multiply(Stream.iterate(BigInteger.valueOf(20), i -> i.add(BigInteger.ONE)).limit(number - 19)
.reduce((previous, current) -> previous.multiply(current)).get()
);
}
}
我觉得我们可以把主要条件改成:
1,vv-1,st 与函数reduce。
也许我们可以在执行主要规则之前进行过滤
我在 Java 8 和 lambda 表达式以及 Stream
方面相对较新,我可以使用 for
循环或递归计算阶乘。但是有没有办法使用 IntStream
来计算一个数的阶乘呢?即使在整数范围内使用阶乘我也很好。
我在这里通读了 IntStream
文档,http://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html 我可以看到很多方法,但不确定我可以使用哪一种来计算阶乘。
例如,rang
方法说,
range(int startInclusive, int endExclusive) Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1.
所以我可以用它来为 IntStream 提供数字范围,乘以计算阶乘。
number = 5;
IntStream.range(1, number)
但是如何将这些数字相乘得到阶乘?
您可以使用 IntStream::reduce 完成这项工作,
int number = 5;
IntStream.rangeClosed(2, number).reduce(1, (x, y) -> x * y)
要获得所有无限阶乘的流,您可以这样做:
class Pair{
final int num;
final int value;
Pair(int num, int value) {
this.num = num;
this.value = value;
}
}
Stream<Pair> allFactorials = Stream.iterate(new Pair(1,1),
x -> new Pair(x.num+1, x.value * (x.num+1)));
allFactorials
是数字的阶乘流,从 1 到 ..... 要获得 1 到 10 的阶乘:
allFactorials.limit(10).forEach(x -> System.out.print(x.value+", "));
它打印: 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
现在假设您只希望得到特定数字的阶乘,然后执行:
allFactorials.limit(number).reduce((previous, current) -> current).get()
最好的部分是您不需要为新数字重新计算,而是建立在历史的基础上。
使用 LongStream.range() 您可以计算小于 20 的数字的阶乘。如果您需要计算更大的数字,请使用 BigInteger 创建流:
public BigInteger factorial(int number) {
if (number < 20) {
return BigInteger.valueOf(
LongStream.range(1, number + 1).reduce((previous, current) -> previous * current).getAsLong()
);
} else {
BigInteger result = factorial(19);
return result.multiply(Stream.iterate(BigInteger.valueOf(20), i -> i.add(BigInteger.ONE)).limit(number - 19)
.reduce((previous, current) -> previous.multiply(current)).get()
);
}
}
我觉得我们可以把主要条件改成: 1,vv-1,st 与函数reduce。 也许我们可以在执行主要规则之前进行过滤