Commons Math学习笔记——函数方程求解

Commons Math学习笔记——函数方程求解

 

看其他篇章到目录选择。

函数方程求解,其实是函数的零点问题,也就是说函数的曲线与X轴的交点。对于线性方程,我们可以轻易的求解,对于线性方程组,利用前面讲过的的矩阵分解方法也可以求解。那么对于函数表达的很多非线性方程的求解。我们要依赖数值算法。Commons Math包中专门有一个analysis.solver包来解决这个问题。

Analysis.solver包中有一个基本接口类——UnivariateRealSolver,其中定义了一系列接口方法,最重要的方法就是double solve(UnivariateRealFunction f, double min, double max)了。很明显,这个方法的参数是函数的表达式以及求解的区间范围,返回值是函数在区间内的一个零值点。

Solver包中的这些类的组织结构形式与积分中的类似,结构类图如下:


 

具体的求解算法有很多,solver包中也实现了很多算法,包括对分法、牛顿法等。我们这里以这两个算法的实现为例,看看该如何使用这个包中的接口方法。待求解的函数仍以正弦函数为例。

 

 1 /** */ /**
 2 * 
 3 */

 4 package  algorithm.math;
 5
 6 import  org.apache.commons.math.ConvergenceException;
 7 import  org.apache.commons.math.FunctionEvaluationException;
 8 import  org.apache.commons.math.analysis.UnivariateRealFunction;
 9 import  org.apache.commons.math.analysis.solvers.BisectionSolver;
10 import  org.apache.commons.math.analysis.solvers.UnivariateRealSolver;
11 import  org.apache.commons.math.analysis.solvers.UnivariateRealSolverFactory;
12 import  org.apache.commons.math.analysis.solvers.UnivariateRealSolverFactoryImpl;
13
14 /** */ /**
15 * @author Jia Yu
16 * @date   2010-11-24
17 */

18 public   class  SolverTest  {
19
20    /** *//**
21     * @param args
22     */

23    public static void main(String[] args) {
24        // TODO Auto-generated method stub
25        solver();
26        factorySolver();
27    }

28
29    private static void factorySolver() {
30        // TODO Auto-generated method stub
31        UnivariateRealFunction f = new SinFunction();
32        UnivariateRealSolverFactory factory=new UnivariateRealSolverFactoryImpl();
33        UnivariateRealSolver solver = factory.newNewtonSolver();
34        try {
35            System.out.println("NewtonSolver : sin(x)=0 when x from -1 to 1, x = "+ solver.solve(f, -11));
36        }
 catch (ConvergenceException e) {
37            // TODO Auto-generated catch block
38            e.printStackTrace();
39        }
 catch (FunctionEvaluationException e) {
40            // TODO Auto-generated catch block
41            e.printStackTrace();
42        }

43    }

44
45    private static void solver() {
46        // TODO Auto-generated method stub
47        UnivariateRealFunction f = new SinFunction();
48        UnivariateRealSolver solver = new BisectionSolver();
49        try {
50            System.out.println("BisectionSolver : sin(x)=0 when x from 3 to 4, x = "+ solver.solve(f, 34));
51        }
 catch (ConvergenceException e) {
52            // TODO Auto-generated catch block
53            e.printStackTrace();
54        }
 catch (FunctionEvaluationException e) {
55            // TODO Auto-generated catch block
56            e.printStackTrace();
57        }

58    }

59
60}

61

 

输出结果:
BisectionSolver : sin(x)=0 when x from 3 to 4, x = 3.141592502593994
NewtonSolver : sin(x)=0 when x from -1 to 1, x = 0.0
 


可以看到,程序都输出了正确的结果。但是,其实还是可以尝试一些复杂的参数来测试算法的,这里就不再多说,不妨看看牛顿法在
(-1,4)区间的效果。

不管是哪种方法,其实都是要设定误差限的,默认的是10E-6

一个小的建议是使用工厂模式的构建方法,因为毕竟这个包内提供了工厂的实现,那为什么不用这种更灵活的方式呢?

写了方程求解的例子,就不要再问什么求平方根的牛顿法或者立方根什么的问题了,不就是x^n-R=0的方程嘛,设定区间[0,+]就可以了。原理明白,其他的问题都很好解决,不是吗?

相关资料:

对分法:http://mathworld.wolfram.com/Bisection.html

牛顿法:http://mathworld.wolfram.com/NewtonsMethod.html

Commons math包:http://commons.apache.org/math/index.html

 



你可能感兴趣的:(Commons Math学习笔记——函数方程求解)