记住从JDK 8 lambda返回的最后一个值

duf*_*ymo 5 java lambda java-8

我为指数函数汇总了Taylor系列扩展的快速Java实现,因为它简单而有趣:

package math.series;

import java.util.stream.IntStream;

/**
 * Created by Michael
 * Creation date 3/6/2016.
 * @link https://stackoverflow.com/questions/35826081/calculating-ex-in-c-sharp
 * @link https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80
 */
public class TaylorSeries {


    public static final int DEFAULT_NUM_TERMS = 10;

    public static void main(String[] args) {
        int n = (args.length > 0) ? Integer.parseInt(args[0]) : DEFAULT_NUM_TERMS;
        System.out.println("pi");
        System.out.println(String.format("%10s %10s %10s %10s", "n", "series", "expected", "error"));
        double expected = Math.PI;
        double series = TaylorSeries.pi(0.0, n);
        double error = expected - series;
        System.out.println(String.format("%10d %10.6f %10.6f %10.6f", n, series, expected, error));

        System.out.println("exp");
        System.out.println(String.format("%10s %10s %10s %10s", "x", "series", "expected", "error"));
        for (double x = 0.0; x <= 3.0; x += 0.25) {
            expected = Math.exp(x);
            series = TaylorSeries.exp(x, n);
            error = expected - series;
            System.out.println(String.format("%10.6f %10.6f %10.6f %10.6f", x, series, expected, error));
        }
    }

    public static double exp(double x, int n) {
        double sum = 1.0;
        double term = 1.0;
        for (int i = 1; i <= n; ++i) {
            term *= x / i;
            sum += term;
        }
        return sum;
    }

    public static double pi(double x, int n) {
        return IntStream.range(0, n)
                .mapToDouble(i -> 8.0/(4*i+1)/(4*i+3))
                .sum();
    }
}
Run Code Online (Sandbox Code Playgroud)

我很惭愧承认我的雇主仍在使用JDK 6和JDK 7; 我在工作期间没有写JDK 8.我还没有弄清楚JDK中的所有新功能,包括lambdas.

我通过使用lambda编写了一个针对pi的泰勒系列扩展来热身.它简单而优雅.令人惊讶的是,它需要一百万个术语才能收敛到六位精度,但这就是该系列本质.

我决定尝试使用lambda实现指数函数.我不想做天真的事情并使用Math.powfactorial功能; 我发布的没有lambdas的实现很好地完成了.

我看不出如何让lambda中的每一步都记住上一个术语的价值.任何人都可以帮助lambda初学者并举个例子吗?

Tun*_*aki 4

一个可能的解决方案是实现一个有状态函数来返回序列中的下一项:

public static double exp(double x, int n) {
    return DoubleStream.iterate(1, new DoubleUnaryOperator() {

        private int i = 1;

        @Override
        public double applyAsDouble(double operand) {
            return operand * x / i++;
        }

    }).limit(n).sum();
}
Run Code Online (Sandbox Code Playgroud)

这将在种子为 1 的方法和返回下一个值的函数DoubleStream的帮助下创建,只需增加当前迭代次数并将前一个值与 相乘。流仅限于元素,并且总和通过 检索。iterate(seed, f)ix / inlimitsum()

调用代码示例:

public static void main(String[] args) {
    System.out.println(exp(3, 500)); // prints "20.085536923187668"
}
Run Code Online (Sandbox Code Playgroud)

结果非常接近真实的