是否有更有效的乘法多项式方法?

时间:2012-10-04 16:24:37

标签: java polynomial-math

这是我将an*x^n + an-1*x^n-1 + ... + a1*x + a0形式的两个多项式相乘的方法。每个Term对象都有两个字段:double coefficientint powerPolynomial通过将术语存储在ArrayList<Term>中来表示多项式。乘法的当前实现是O(n ^ 2)。关于如何加快速度的任何想法或提示?

public Polynomial multiply(Polynomial P2) {
    PolynomialImp result = new PolynomialImp();
    for (Term currentThisTerm : this.terms)
    {
        for (Term currentP2Term : ((PolynomialImp) P2).terms)
        {
            result.addTerm(new TermImp(currentThisTerm.getCoefficient()*currentP2Term.getCoefficient(), currentThisTerm.getExponent() + currentP2Term.getExponent()));
        }
    }
    //Sort polynomial in decreasing exponent order
    return result.sort();
}

如果需要,下面是addTerm方法:

private void addTerm(Term nextTerm)
{
    for (int i = 0; i < this.terms.size(); i++)
    {
        if (this.terms.get(i).getExponent() == nextTerm.getExponent())
        {
            //Add the coefficients if the current term has the same exponent as a term that is already in the polynomial.
            //This preserves the sorting of the polynomial except during multiply.
            this.terms.set(i, new TermImp(this.terms.get(i).getCoefficient() + nextTerm.getCoefficient(), this.terms.get(i).getExponent()));
            return;
        }
    }
    //Avoid adding zeros to the polynomial.
    if (nextTerm.getCoefficient() != 0)
        this.terms.add(nextTerm);
}

3 个答案:

答案 0 :(得分:4)

这就是我实现此功能的方法

public class Polynomial {
    private final double[] coeff;

    public Polynomial(double... coeff) {
        this.coeff = coeff;
    }

    @Override
    public String toString() {
        return Arrays.toString(coeff);
    }

    public Polynomial multiply(Polynomial polynomial) {
        int totalLength = coeff.length + polynomial.coeff.length - 1;
        double[] result = new double[totalLength];
        for (int i = 0; i < coeff.length; i++)
            for (int j = 0; j < polynomial.coeff.length; j++) {
                result[i + j] += coeff[i] * polynomial.coeff[j];
            }
        return new Polynomial(result);
    }

    public static void main(String... args) {
        Polynomial p1 = new Polynomial(1, 2, 3);
        System.out.println(p1 + "^2 =" + p1.multiply(p1));
        Polynomial p2 = new Polynomial(3, -1, -1);
        System.out.println(p1 + "*" + p2 + "=" + p1.multiply(p2));
    }
}

打印

[1.0, 2.0, 3.0]^2 =[1.0, 4.0, 10.0, 12.0, 9.0]
[1.0, 2.0, 3.0]*[3.0, -1.0, -1.0]=[3.0, 5.0, 6.0, -5.0, -3.0]

答案 1 :(得分:1)

可能使这个算法变慢的原因是创建n ^ 2个TermImp对象。在C ++中,这应该不是问题,因为您将在堆栈上创建对象并按值传递。我的理解是,在Java中你没有这个选项:你必须接受创建一个对象的开销,然后通过引用传递。

每次乘以一个术语时,创建一个新对象似乎效率低下。难道你不能消除它吗?

您可以考虑更改addTerm方法以接受系数和指数作为double / int参数。

对于大n,算法仍然是O(n ^ 2),但它仍然应该加速很多。

你可以考虑的另一件事是使用for循环而不是迭代器,因为迭代器也涉及创建新对象......虽然O(n)因此不那么重要。

答案 2 :(得分:0)

您有一个主要的低效率:您将条款存储在看似无序的列表中。您应该修改代码,以便terms.get(n)返回带有x ^ n的术语。然后,您不需要在addTerm方法中搜索terms变量。

为此,您必须更新修改条款的所有代码以保持条款的有序性。

乘法方法本身看起来很有效,我认为它不能再进行优化。