目录
前言:
最近在Android app实时显示数据上遇到了个问题,就是获取的数据需要进行转换。这里的转换公式为双指数函数,反函数不好转化出一个式子,需要实现非线性方程的求解寻根。
以往完成这个操作,我是在matlab定义函数式用fslove求解来完成这件事情,我在思考是否可以在Android app上实现这一点。经过一些调研,的确是可以的,可以使用Apache-commons-math3来实现。
一、Apache-commons-math3介绍
Apache-commons-math3是java的一种科学计算库,平日里接触数学计算更多是在matlab或者python上实现,在Android Java上实现的相关资料比较少。这里简要简要介绍一下apache-commons-math3,大致了解它能够做些什么,详细的使用可以去研究官方文档。
math3可以支持的功能如下所示:
- 支持常用的矩阵操作,例如矩阵转置、求逆以及加减乘除等
- 支持矩阵分解操作,例如LU分解、QR分解、奇异值分解、特征值分解等
- 可以实现一些数理统计的方法,例如t检验、卡方检验等等
- 可以实现一些基本的数值方法,例如插值、曲线拟合、积分、最小二乘、线性回归等等
- 可以实现非线性方程组的求解寻根。
其中矩阵的运算是可以应用到多个场景,例如线性方程组求解、图像处理、信号处理以及机器学习和数据分析等;信号处理方面,常见的如傅里叶变换以及滤波处理;对于机器学习和数据分析,常见的特征矩阵被用于存储数据特征,线性代数中的运算方法常应用于模型训练和预测。
二、具体实例
以上apache-commons-math3有很多的功能,这里我只讲述非线性方程组求解的实例。实现双指数单变量函数的求解寻根。
2.1 导入函数类
import org.apache.commons.math3.analysis.UnivariateFunction; //单变量实数类
import org.apache.commons.math3.analysis.solvers.BrentSolver; //布伦特法
import org.apache.commons.math3.analysis.solvers.MullerSolver; //米勒(Muller)法
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; //处理函数微分的类
import org.apache.commons.math3.analysis.solvers.NewtonRaphsonSolver;//Newton-Raphson法
import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;//函数类
import org.apache.commons.math3.exception.DimensionMismatchException;
2.2 定义函数接口
这里我们先进行初始化,这里是使用了单变量实函数类UnivariateFunction,对应方法布伦特法和米勒法。函数较为复杂,双指数函数:3323 * exp(-5.647 * x) + 239.2 * exp(-0.5883 * x) - data。注:data为实时获取的数据。
UnivariateFunction function = new UnivariateFunction() {
@Override
public double value(double x) {
//data为实时获取的数据
return (3323 * Math.exp(-5.647 * x) + 239.2 * Math.exp(-0.5883 * x) - data);
}
};
2.3 使用求解器
这里讲述一些我应用实践的求解器,求解函数方程的根。
2.3.1 布伦特法(Brent)
/*初始化求解器*/
/*布伦特法(混合寻根算法,结合了平方法、分割法和逆二次插值法)
* */
BrentSolver brentSolver = new BrentSolver(1e-9);
/*求根*/
/*迭代次数、函数以及最小值和最大值*/
/*0.5ms*/
double res = brentSolver.solve(500,function,-5,8);
2.3.2 米勒(Muller)法
/*初始化求解器*/
/*米勒法*/
MullerSolver mullerSolver = new MullerSolver(1e-9);
/*求根*/
/*迭代次数、函数以及最小值和最大值*/
double res = mullerSolver.solve(500,function,-10,10);
2.3.3 Newton-Raphson法
//需要用到微分
//定义函数
UnivariateDifferentiableFunction function = new UnivariateDifferentiableFunction() {
@Override
public DerivativeStructure value(DerivativeStructure t) throws DimensionMismatchException {
double x = t.getValue();
double result = (3323 * Math.exp(-5.647 * x) + 239.2 * Math.exp(-0.5883 * x) - data);
//返回函数值以及一阶导数
return new DerivativeStructure(1,1,0,result);
}
@Override
public double value(double x) {
return (3323 * Math.exp(-5.647 * x) + 239.2 * Math.exp(-0.5883 * x) - resistence);
}
};
NewtonRaphsonSolver newtonRaphsonSolver = new NewtonRaphsonSolver(1e-9);
//迭代次数、函数以及初始值
double res = newtonRaphsonSolver.solve(500,function,0);