简体   繁体   English

计算多项式的最有效方法

[英]Most efficient way to compute a polynomial

Polynomial: a0x^0 + a1x^1 +a2x^2 + a3x^3 + ... + anx^n 多项式:a0x ^ 0 + a1x ^ 1 + a2x ^ 2 + a3x ^ 3 + ... + anx ^ n

Array: array_a[] = {a0, a1, a2, a3 ... an}; 数组:array_a [] = {a0,a1,a2,a3 ... an};

I wrote a function to calculate this polynomial in Java: 我写了一个函数来计算Java中的这个多项式:

public double cal(double x) {
    double y = 0.0;
    for (int index = array_a.length - 1; index >= 0; index--) {
        y = array_a[index] + y * x;
    }
    return y;
}

This seems 5 times faster than the loop y += array_a[index] * Math.Pow(x, index); 这似乎比循环y += array_a[index] * Math.Pow(x, index);y += array_a[index] * Math.Pow(x, index);快5倍y += array_a[index] * Math.Pow(x, index);

But I wondering if there is a better way to compute this polynomial? 但我想知道是否有更好的方法来计算这个多项式?

** For anyone thinks it's a different calculation: I did test the function above. **对于任何人都认为这是一个不同的计算:我测试了上面的功能。 It does the same thing with y += array_a[index] * Math.Pow(x, index); 它与y += array_a[index] * Math.Pow(x, index); and they compute the same result. 他们计算相同的结果。

Thanks. 谢谢。

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的方法只需要n次加法和n次乘法,其存储要求只是x的位数的n倍。 ...

Horner's method is optimal, in the sense that any algorithm to evaluate an arbitrary polynomial must use at least as many operations. Horner的方法是最优的,因为评估任意多项式的任何算法必须至少使用尽可能多的运算。 Alexander Ostrowski proved in 1954 that the number of additions required is minimal. 亚历山大·奥斯特罗夫斯基(Alexander Ostrowski)在1954年证明,所需的增加数量很少。 Victor Pan proved in 1966 that the number of multiplications is minimal. Victor Pan在1966年证明了乘法的次数很少。

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. 如果你需要非常多的时间评估多项式和程度是非常高的,然后有改造多项式( 预处理 )的表示方法,这样乘法的数量减少到⌊N /2⌋+ 2,这似乎虽然不太实用,但至少我从来没有在野外看过这个。 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: 在本文中还提到,由于CPU架构,如果分别评估偶数和奇数项,可能会更有效,因此可以将它们放在并行管道中:

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. JIT /编译器可能能够为您执行此转换,甚至可以使用SIMD使其自动化速度非常快。 Anyway, for this kind of micro-optimization, always profile before committing to a final solution. 无论如何,对于这种微优化,总是在提交最终解决方案之前进行概述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM