This is Horner's method. If you only want to calculate it once per polynomial, this is the most efficient algorithm:
… Horner's method requires only n additions and n multiplications, and its storage requirements are only n times the number of bits of x. …
Horner's method is optimal, in the sense that any algorithm to evaluate an arbitrary polynomial must use at least as many operations. Alexander Ostrowski proved in 1954 that the number of additions required is minimal. Victor Pan proved in 1966 that the number of multiplications is minimal.
If you need to evaluate the polynomial extremely many times and the degree is very high, then there are methods to transform the representation of the polynomial (preconditioning) so that the number of multiplication is reduced to ⌊n/2⌋ + 2. This seems not very practical though, at least I've never seen this in the wild. I've found an online paper that describes some of the algorithms if you are interested.
Also mentioned in the paper, due to the CPU architecture it might be more efficient if you evaluating even and odd terms separately so they can be placed in parallel pipelines:
public double cal(double x) {
double x2 = x * x;
double y_odd = 0.0, y_even = 0.0;
int index = array_a.length - 1;
if (index % 2 == 0) {
y_even = array_a[index];
index -= 1;
}
for (; index >= 0; index -= 2) {
y_odd = array_a[index] + y_odd * x2;
y_even = array_a[index-1] + y_even * x2;
}
return y_even + y_odd * x;
}
The JIT/compiler might be able to do this conversion for you or even use SIMD to make it very fast automagically. Anyway, for this kind of micro-optimization, always profile before committing to a final solution.
double y = 0; double x_n = 1; for (i = 0; i < length; i++) { y += array[i] * x_n; x_n *= x; }
- performance wise it's probably equivalent to your version. – Nernstn
add operations andn+1
multiply operations. That cannot be reduced. By using thea0 + x * (a1 + x*(a2 +... ))
formula, you have successfully eliminated the power operations. Well, technically, multiplying byx^0
can be eliminated, so onlyn
multiply operations. Your code is currently doingn+1
adds and multiply's, so you could twiddle it slightly. Note thatn = array_a.length - 1
. – Gentoodouble y = array_a[array_a.length -1]
and then only run the loop fromarray_a.length-2
. But that's such a marginal gain that it's hardly worth the slightly reduced readability. – Teenya0
and so on. – Teeny