Παράδειγμα: Υλοποίηση √2 με NR

Το παρακάτω παράδειγμα υπολογίζει τη √2 δημιουργώντας μια άπειρου μήκους ακολουθία με διαδοχικά καλύτερες προσεγγίσεις.

import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.DoubleFunction;
import java.util.stream.Stream;


/** Find a square root using the Newton-Raphson approximation */
class SquareRoot {

    /** Obtain successive approximations of a function's root using the
     * Newton-Raphson method. */
    static class NewtonRaphson {
        /** f(x) and f'(x) */
        DoubleFunction fx, fdx;

        NewtonRaphson(DoubleFunction fx, DoubleFunction fdx) {
            this.fx = fx;
            this.fdx = fdx;
        }

        /** Return next approximation, given the previous one */
        Double nextApproximation(double previous) {
            // xₙ₊₁ = xₙ - f(xₙ) / f′(xₙ)
            return previous - (double)fx.apply(previous) / (double)fdx.apply(previous);
        }
    }

    /** Test whether successive parts of a series differ more than a value */
    static class NotWithin implements Predicate<Double> {
        /** Previous value in series */
        Optional<Double> previous = Optional.empty();
        /** Difference value above which the test method returns true */
        Double epsilon;

        NotWithin(double d) {
            epsilon = d;
        }

        /**
         * Return true if successive parts of the series do not differ by
         * less than the specified epsilon.
         */
        @Override
        public boolean test(Double d) {
            boolean r;

            if (previous.isPresent())
                r = (Math.abs(previous.get() - d) > epsilon);
            else
                r = true;
            previous = Optional.of(d);
            return r;
        }
    }

    public static void main(String args[]) {
        final double SQRT_TO_FIND = 2;
        DoubleFunction fx = (x -> x * x - SQRT_TO_FIND); // f(x) = x² - α
        DoubleFunction fdx = (x -> 2 * x); // f'(x) = 2x
        var rootTwo = new NewtonRaphson(fx, fdx);
        var greaterThanEpsilon = new NotWithin(1e-15);

	// SQRT_TO_FIND is also our first approximation
        System.out.println(Stream.iterate(SQRT_TO_FIND, rootTwo::nextApproximation)
            .dropWhile(greaterThanEpsilon)
            .findFirst()
            .get());
    }
}