2.2 多項式函數
看其他篇章到目錄選擇。
在Commons Math中的analysis.polynomials包中有所有的與多項式函數相關的類和接口定義。這一篇主要從這個包分析,來研究一下多項式函數的應用。
Polynomials包中沒有interface的定義,下屬含有5個類:PolynomialFunction、PolynomialFunctionLagrangeForm、PolynomialFunctionNewtonForm、PolynomialSplineFunction和PolynomialsUtils。其中主要的只有PolynomialFunction和PolynomialSplineFunction,正如api doc中的介紹,PolynomialFunction類是Immutable representation of a real polynomial function with real coefficients——實數多項式的表示;PolynomialSplineFunction類是Represents a polynomial spline function.——樣條曲線多項式的表示。另外兩個表示拉格朗日和牛頓形式的多項式函數。而PolynomialsUtils類中提供了幾個構造個別(比如切比雪夫多項式)多項式的靜態方法。
我覺得最常用的應該就是實數系數的多項式了,因此以PolynomialFunction類為例來進行分析。實數系數的多項式函數形如:f(x) = ax^2 + bx + c。PolynomialFunction類實現了DifferentiableUnivariateRealFunction接口,因此必須實現value()和derivative()方法,并且實現該接口也表明這是一元可微分的實數函數形式。PolynomialFunction類定義了一組final double coefficients[]作為多項式系數,其中coefficients[0]表示常數項的系數,coefficients[n]表示指數為n的x^n次項的系數。因此,這個類所表達的多項式函數是這樣的:f(x)=coeff[0] + coeff[1]x + coeff[2]x^2 + … + coeff[n]x^n。它的構造方法是PolynomialFunction(double [])就是接受這樣的coefficients數組作為系數輸入參數來構造多項式的。這個是很好表達也很方便理解的。那么它的value(double x)方法是通過調用double evaluate(double[] coefficients, double argument)實現的,本質用Horner's Method求解多項式的值,沒有什么技術難點,非常好理解的一個給定參數和函數求值過程。剩余定義的一些加減乘等操作,都是通過一個類似public PolynomialFunction add(final PolynomialFunction p)這樣的結構實現的。求導數的方法derivative()是通過這樣的一個微分操作實現的。見源碼:
1
protected static double[] differentiate(double[] coefficients)
{
2
int n = coefficients.length;
3
if (n < 1)
{
4
throw MathRuntimeException.createIllegalArgumentException("empty polynomials coefficients array");
5
}
6
if (n == 1)
{
7
return new double[]
{0};
8
}
9
double[] result = new double[n - 1];
10
for (int i = n - 1; i > 0; i--)
{
11
result[i - 1] = i * coefficients[i];
12
}
13
return result;
14
}
15
測試代碼示例如下:
1
/** *//**
2
*
3
*/
4
package algorithm.math;
5
6
import org.apache.commons.math.ArgumentOutsideDomainException;
7
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
8
import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
9
10
/** *//**
11
* @author Jia Yu
12
* @date 2010-11-21
13
*/
14
public class PolinomialsFunctionTest
{
15
16
/** *//**
17
* @param args
18
*/
19
public static void main(String[] args)
{
20
// TODO Auto-generated method stub
21
polynomials();
22
System.out.println("-----------------------------------------------");
23
polynomialsSpline();
24
}
25
26
private static void polynomialsSpline()
{
27
// TODO Auto-generated method stub
28
PolynomialFunction[] polynomials =
{
29
new PolynomialFunction(new double[]
{ 0d, 1d, 1d }),
30
new PolynomialFunction(new double[]
{ 2d, 1d, 1d }),
31
new PolynomialFunction(new double[]
{ 4d, 1d, 1d }) };
32
double[] knots =
{ -1, 0, 1, 2 };
33
PolynomialSplineFunction spline = new PolynomialSplineFunction(knots,
34
polynomials);
35
//output directly
36
System.out.println("poly spline func is "+spline);
37
// get the value when x = 0.5
38
try
{
39
System.out.println("f(0.5) = "+spline.value(0.5));
40
} catch (ArgumentOutsideDomainException e)
{
41
// TODO Auto-generated catch block
42
e.printStackTrace();
43
}
44
// the number of spline segments
45
System.out.println("spline segments number is "+spline.getN());
46
// the polynomials functions
47
for(int i=0;i<spline.getN();i++)
{
48
System.out.println("spline:f"+i+"(x) = "+spline.getPolynomials()[i]);
49
}
50
//function derivative
51
System.out.println("spline func derivative is "+spline.derivative());
52
}
53
54
private static void polynomials()
{
55
// TODO Auto-generated method stub
56
double[] f1_coeff =
{ 3.0, 6.0, -2.0, 1.0 };
57
double[] f2_coeff =
{ 1.0, 2.0, -1.0, -2.0 };
58
PolynomialFunction f1 = new PolynomialFunction(f1_coeff);
59
PolynomialFunction f2 = new PolynomialFunction(f2_coeff);
60
// output directly
61
System.out.println("f1(x) is : " + f1);
62
System.out.println("f2(x) is : " + f2);
63
// polynomial degree
64
System.out.println("f1(x)'s degree is " + f1.degree());
65
// get the value when x = 2
66
System.out.println("f1(2) = " + f1.value(2));
67
// function add
68
System.out.println("f1(x)+f2(x) = " + f1.add(f2));
69
// function substract
70
System.out.println("f1(x)-f2(x) = " + f1.subtract(f2));
71
// function multiply
72
System.out.println("f1(x)*f2(x) = " + f1.multiply(f2));
73
// function derivative
74
System.out.println("f1'(x) = " + f1.derivative());
75
System.out.println("f2''(x) = "
76
+ ((PolynomialFunction) f2.derivative()).derivative());
77
78
}
79
80
}
81
輸出如下:
f1(x) is : 3.0 + 6.0 x - 2.0 x^2 + x^3
f2(x) is : 1.0 + 2.0 x - x^2 - 2.0 x^3
f1(x)'s degree is 3
f1(2) = 15.0
f1(x)+f2(x) = 4.0 + 8.0 x - 3.0 x^2 - x^3
f1(x)-f2(x) = 2.0 + 4.0 x - x^2 + 3.0 x^3
f1(x)*f2(x) = 3.0 + 12.0 x + 7.0 x^2 - 15.0 x^3 - 8.0 x^4 + 3.0 x^5 - 2.0 x^6
f1'(x) = 6.0 - 4.0 x + 3.0 x^2
f2''(x) = -2.0 - 12.0 x
-----------------------------------------------
poly spline func is org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction@69b332
f(0.5) = 2.75
spline segments number is 3
spline:f0(x) = x + x^2
spline:f1(x) = 2.0 + x + x^2
spline:f2(x) = 4.0 + x + x^2
spline func derivative is org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction@173a10f
PolynomialFunction類也是重寫了toString方法和hashCode和equals方法的。
PolynomialSplineFunction類是多項式樣條函數,樣條是一種特殊的函數,由多項式分段定義。表示了一個由多個多項式組成的樣條曲線。它的實現主要是內部定義了一個多項式函數組PolynomialFunction polynomials[]和一個樣條分界節點數組double knots[]。這兩個內部成員分別表示什么呢?分界節點表示整條曲線對應在x等于knots[i]的時候開始使用其他多項式樣條,其構造方法public PolynomialSplineFunction(double knots[], PolynomialFunction polynomials[])完成這樣的功能。
舉例來說,一個多項式樣條函數就是一個分段函數:
X^2+x [-1,0)
F(x) = x^2+x+2 [0,1)
X^2+x+4 [1,2)
當然,構造方法中的參數,knots[]數組必須是遞增的。
可以看到,直接輸出PolynomialSplineFunction是多么丑陋啊~~,因為它沒有重寫toString方法。同樣,它的導數也是一樣的丑陋。其中如果給定的值不在定義域內,value方法還拋出異常ArgumentOutsideDomainException。
最后PolynomialFunctionLagrangeForm和PolynomialFunctionNewtonForm類完成的其實是多項式插值的功能,放到下一節研究的。
相關資料:
多項式:http://zh.wikipedia.org/zh-cn/%E5%A4%9A%E9%A1%B9%E5%BC%8F%E5%87%BD%E6%95%B0#.E5.A4.9A.E9.A0.85.E5.BC.8F.E5.87.BD.E6.95.B8.E5.8F.8A.E5.A4.9A.E9.A0.85.E5.BC.8F.E7.9A.84.E6.A0.B9
樣條函數:http://zh.wikipedia.org/zh-cn/%E6%A0%B7%E6%9D%A1%E5%87%BD%E6%95%B0
Horner Methods:http://mathworld.wolfram.com/HornersMethod.html
Commons math包:http://commons.apache.org/math/index.html