【问题标题】:Most efficient way to compute a polynomial计算多项式的最有效方法
【发布时间】:2016-08-30 15:13:10
【问题描述】:

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

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

我用 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;
}

这似乎比循环 y += array_a[index] * Math.Pow(x, index); 快 5 倍

但我想知道是否有更好的方法来计算这个多项式?

** 对于任何认为这是不同的计算的人:我确实测试了上面的函数。它对y += array_a[index] * Math.Pow(x, index); 执行相同的操作,并且它们计算相同的结果。

谢谢。

【问题讨论】:

  • 他使用多项式等于 a0 + x * (a1 + x*(a2 +... ))
  • @ErwinBolwidt 是的,我做到了。我知道这看起来像是一个不同的计算。但它做同样的事情。你可以检查一下。
  • 有更好的方法吗?这似乎已经是最好的方法了。最少的计算次数。你问来干什么?你不喜欢哪个部分?
  • @Andreas 是的,我想是的。这是最好的方法,但我的教授仍然要求她的学生对此进行优化。所以我正在努力寻找更好的方法。
  • 不管怎么弄,都得执行n加操作和n+1乘操作。那是不能减少的。通过使用a0 + x * (a1 + x*(a2 +... )) 公式,您已经成功消除了幂运算。好吧,从技术上讲,乘以x^0 可以消除,所以只有n 乘法运算。您的代码目前正在执行n+1 加法和乘法运算,因此您可以稍微调整一下。 注意n = array_a.length - 1

标签: java polynomial-math


【解决方案1】:

这是霍纳的方法。如果您只想每个多项式计算一次,this is the most efficient algorithm:

…Horner的方法只需要n次加法和n次乘法,其存储要求只有nx。 …

Horner 的方法是最优的,因为任何计算任意多项式的算法都必须至少使用同样多的操作。 Alexander Ostrowski 在 1954 年证明了所需的添加数量是最少的。 Victor Pan 在 1966 年证明了乘法的次数是最少的。

如果您需要对多项式进行非常多次的求值并且次数非常高,那么有一些方法可以对多项式的表示进行变换(preconditioning),从而将乘法的次数减少到⌊n/2⌋ + 2。但这似乎不太实用,至少我从未在野外见过。 I've found an online paper that describes some of the algorithms if you are interested

在论文中也提到,由于 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;
}

JIT/编译器可能会为您完成这种转换,甚至可以使用 SIMD 自动使其非常快速。无论如何,对于这种微优化,总是在提交最终解决方案之前进行分析。

【讨论】:

    猜你喜欢
    • 2014-07-26
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    相关资源
    最近更新 更多