Apache Commons Math3学习之数值积分实例代码
apache.commons.math3里面的数值积分支持类采用的是“逼近法”,即,先对大区间做一次积分,再对小区间做一次积分,若两次积分结果的差值小于某一设定的误差值,则认为积分完成。否则,将区间再次细分,对细分后的区间进行积分,与前一次积分相比较,如此反复迭代,直至最近的两次积分差值足够小。这样的结果,有可能会导致无法收敛。
为了使用org.apache.commons.math3.analysis.integration包中的积分器类,需要先实现univariatefunction接口(本文以myfunction为例),实现其value方法。然后创建指定的积分器对象,本文以simpsonintegrator为例,最后调用其integrate(...)方法即可算出myfunction的积分。
调用integrate(...)方法时需要提供4个参数:
第1个是最大逼近次数,要适当大一些,否则可能会无法收敛;
第2个是myfunction类的实例;
第3个是积分区间下限;
第4个是积分区间上限。
simpsonintegrator在第一次迭代时一定是分别以积分下限和积分上限作为x调用连词myfunction.value(...)方法,下一次则会将区间分成2份(除上下限x值之外,还有一个中间x值),再下一次则是分成4份……
以下是使用辛普森积分类的例子:
import java.util.arraylist; import java.util.list; import org.apache.commons.math3.analysis.univariatefunction; import org.apache.commons.math3.analysis.integration.simpsonintegrator; import org.apache.commons.math3.analysis.integration.univariateintegrator; interface testcase { public object run(list<object> params) throws exception; public list<object> getparams(); public void printresult(object result) throws exception; } public class timecostcalculator { public timecostcalculator() { } /** * 计算指定对象的运行时间开销。 * * @param testcase 指定被测对象。 * @return 返回sub.run的时间开销,单位为s。 * @throws exception */ private double calctimecost(testcase testcase) throws exception { list<object> params = testcase.getparams(); long starttime = system.nanotime(); object result = testcase.run(params); long stoptime = system.nanotime(); testcase.printresult(result); double timecost = (stoptime - starttime) * 1.0e-9; return timecost; } public void runtest(testcase testcase) throws exception { double timecost = calctimecost(testcase); system.out.println("时间开销:: " + timecost + "s"); system.out.println("-------------------------------------------------------------------------------"); } public static void main(string[] args) throws exception { timecostcalculator tcc = new timecostcalculator(); tcc.runtest(new calcsimpsonintegrator()); } } /** * 使用辛普森法求解数值积分。apache.common.math3中所用的辛普森法是采用逼近法,即先对整个积分区间用矩形积分,然后将区间分解为4份,再次积分,比较两次积分的差值,若想对误差大于某个预订数值, * 则认为还需要继续细分区间,因此会将区间以2倍再次细分后求积分,并将结果与前一次积分的结果比较,直至差值小于指定的误差,就停止。 * @author kingfox * */ class calcsimpsonintegrator implements testcase { public calcsimpsonintegrator() { system.out.print("本算例用于测试使用辛普森法计算积分。正在初始化计算数据 ... ..."); inputdata = new double[arraylength]; for (int index = 0; index < inputdata.length; index++) // 鏂滃潯鍑芥暟 { inputdata[index] = math.sin(2 * math.pi * index * myfunction.factor * 4); } func = new myfunction(); integrator = new simpsonintegrator(); system.out.println("初始化完成!"); } @override public object run(list<object> params) throws exception { double result = ((simpsonintegrator)(params.get(1))).integrate(steps, (univariatefunction)(params.get(0)), lower, upper); return result; } /** * 获取运行参数 * @return list对象,第一个元素是求积函数,第二个参数是积分器。 */ @override public list<object> getparams() { list<object> params = new arraylist<object>(); params.add(func); params.add(integrator); return params; } @override public void printresult(object result) throws exception { system.out.println(">>> integration value: " + result); } univariatefunction func = null; univariateintegrator integrator = null; class myfunction implements univariatefunction { @override public double value(double x) { // double y = x * factor; // 1. // double y = 4.0 * x * x * x - 3.0 * x * x + 2.0 * x - 1.0; // 2. // double y = -1.0 * math.sin(x) + 2.0 * math.cos(x) - 3.0; // 3. double y = inputdata[(int)(x / factor)]; // 4. // system.out.println(x + ", " + y); return y; } private static final double factor = 0.0001; } private double[] inputdata = null; private static final int arraylength = 5000; private static final double lower = 0.0; // private static final double upper = 2.0 * math.pi; // 3. private static final double upper = (arraylength - 1) * myfunction.factor; // 1. 2. 4. private static final int steps = 1000000; }
上述代码中,注释为1. 2. 3.的可以正常计算出结果,但注释为4.的就无法收敛。
基于org.apache.commons.math3.analysis.integration.univariateintegrator的积分器的另一个局限性在于必须编写一个继承于univariatefunction的函数类,实现其value方法(根据输入的x值计算出y值),这种做法有利于可用解析式表达的情况,不利于对存放于外存的大量数据做积分处理。
总结
以上就是本文关于apache commons math3学习之数值积分实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:java 蒙特卡洛算法求圆周率近似值实例详解、等,有什么问题可以随时留言,小编会及时回复大家的。这里推荐几本java方面的书,供广大编程爱好及工作者进行阅读参考,免费的哦!
java初级开发工程师面试题汇总.pdf
java jdk1.9 api 中文参考文档+原版文档 高清完整版 chm
希望大家能够喜欢,希望对本站多多支持!
上一篇: Python 字符串大小写转换的简单实例
下一篇: log4j使用详细解析