简体   繁体   English

使用 Java 8 IntStream 计算阶乘?

[英]calculating factorial using Java 8 IntStream?

I am relatively new in Java 8 and lambda expressions as well as Stream , i can calculate factorial using for loop or recursion.我在 Java 8 和 lambda 表达式以及Stream中相对较新,我可以使用for循环或递归计算阶乘。 But is there a way to use IntStream to calculate factorial of a number ?但是有没有办法使用IntStream来计算一个数字的阶乘? I am fine even with factorial in integer range.即使在整数范围内使用阶乘我也很好。

I read through IntStream docs here, http://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html and i can see so many methods but not sure which one I can use to calculate factorial.我在这里阅读了IntStream文档, http: //docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html,我可以看到很多方法,但不确定我可以使用哪一个计算阶乘。

for example, there is rang method that says,例如,有rang方法说,

range(int startInclusive, int endExclusive) Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1. range(int startInclusive, int endExclusive) 以增量 1 返回从 startInclusive(包含)到 endExclusive(不包含)的顺序有序 IntStream。

so I can use it to provide the range of numbers to IntStream to be multiplied to calculate factorial.所以我可以用它来为 IntStream 提供要相乘以计算阶乘的数字范围。

number = 5;
IntStream.range(1, number)

but how to multiply those numbers to get the factorial ?但是如何将这些数字相乘以获得阶乘?

You can use IntStream::reduce for this job,您可以将IntStream::reduce用于此作业,

int number = 5;
IntStream.rangeClosed(2, number).reduce(1, (x, y) -> x * y)

To get a stream of all infinite factorials, you can do:要获得所有无限阶乘的流,您可以执行以下操作:

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 is a stream of factorials of number starting from 1 to ..... To get factorials of 1 to 10: allFactorials是从 1 到 ..... 的数字阶乘流 要获得 1 到 10 的阶乘:

allFactorials.limit(10).forEach(x -> System.out.print(x.value+", "));

It prints: 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,它打印:1、2、6、24、120、720、5040、40320、362880、3628800、

Now say you only wish to have a factorial of a particular number then do:现在说你只希望有一个特定数字的阶乘然后做:

allFactorials.limit(number).reduce((previous, current) -> current).get()

The best part is that you dont recompute again for new numbers but build on history.最好的部分是您不会再次为新数字重新计算,而是建立在历史的基础上。

With LongStream.range() you can calculate factorial for number less 20. If you need calculate for larger number create stream with BigInteger:使用 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()
        );
    }
}

We can solve the question with AtomicInteger like this:我们可以像这样用 AtomicInteger 解决这个问题:

  int num = 5;
  AtomicInteger sum = new AtomicInteger(1);
  IntStream.rangeClosed(2, num).forEach(i -> {
    sum.updateAndGet(v -> v * i);
        if (i == num) {
          System.out.println(sum.get());
        }
  });

I think we can change the main condition to: 1,v v-1,s t with the function reduce.我认为我们可以将主要条件更改为: 1,v v-1,s t 使用函数 reduce。 Maybe we can filter before we did the main rule也许我们可以在执行主要规则之前进行过滤

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM