Java Stream API has method Stream::iterate
starting from Java 9, therefore a class representing the iteration steps/states may be implemented as follows:
class CubeSolver {
static final double EPS = 1E-06;
private double start, end, n, mid;
public CubeSolver(double s, double e, double n) {
this.start = s;
this.end = e;
this.n = n;
this.mid = (start + end) / 2;
}
// UnaryOperator<CubeSolver> for iteration
public CubeSolver next() {
if (done()) {
return this;
}
if (Math.pow(mid, 3) < n) {
start = mid;
} else if (Math.abs(n - Math.pow(mid, 3)) > EPS) {
end = mid;
}
return new CubeSolver(start, end, n);
}
// define end of calculation
public boolean done() {
return mid == 0 || Math.abs(n - Math.pow(mid, 3)) < EPS;
}
@Override
public String toString() {
return "root = " + mid;
}
}
Then the stream-based solution looks like this:
- define an initial seed with
start
, end
, n
- use
Stream::iterate
with hasNext
predicate to create a finite stream
2a) or use older Stream::iterate
without hasNext
but with Stream::takeWhile
operation to conditionally limit the stream - also available since Java 9
- use
Stream::reduce
to get the last element of the stream
CubeSolver seed = new CubeSolver(1.8, 2.8, 8);
CubeSolver solution = Stream
.iterate(seed, cs -> !cs.done(), CubeSolver::next)
.reduce((first, last) -> last) // Optional<CubeSolver>
.orElse(null);
System.out.println(solution);
Output:
root = 2.0000002861022947
In Java 11 static Predicate::not
was added, so the 2a solution using takeWhile
could look like this:
CubeSolver seed = new CubeSolver(0, 7, 125);
CubeSolver solution = Stream
.iterate(seed, CubeSolver::next)
.takeWhile(Predicate.not(CubeSolver::done))
.reduce((first, last) -> last) // Optional<CubeSolver>
.orElse(null);
System.out.println(solution);
Output (for EPS = 1E-12):
root = 4.999999999999957