Issue
I have this algorithm right here,
while ((start + end) / 2 != 0) {
Double mid = (start + end) / 2;
if (Math2.pow(mid, 3) < n) {
start = mid;
} else if (Math.abs(n - Math2.pow(mid, 3)) > Math2.pow(e, 3)) {
end = mid;
} else if (Math.abs(n - Math2.pow(mid, 3)) < Math2.pow(e, 3)) {
return mid;
}
}
return 0.0;
}
that gives me the cubic root of n with a loss precision of e. I need to do the same thing but using Java 8 Streams. Math2 is from a private git rep. You can use Math.pow instead; it will work too. How can I do the same algorithm with Streams?
Solution
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
withhasNext
predicate to create a finite stream 2a) or use olderStream::iterate
withouthasNext
but withStream::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
Answered By - Alex Rudenko