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() 是通过这样的一个微分操作实现的。见源码:
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
测试代码示例如下:
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/%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