〖数学算法〗积分算法(一)
来源:互联网 发布:电信机顶盒克隆mac 编辑:程序博客网 时间:2024/06/08 13:05
当我上小学的时,就学习了球的体积公式V=(4/3)πR³,当时觉得它实在太神奇了,是不是求得这个公式的人把一个铁球熔成铁水,放在一个矩形容器中求的?直到大上学才知道是利用积分算得的,当然微积分这个东西对于包括我在内的广大同学们来说可能是恨大于爱,但不可否认是积分在几乎所有理工学科都有着无可替代的作用,所以博主就写一写求积分的算法,由于算法过多,为了避免篇幅过长,给读者造成疲劳感,我决定分4篇写积分算法。
唯一方便统一,本篇各算法均以这个最基本式子的来作例子
1.随机投点法(蒙特卡洛算法)
在求圆周率的文章中已经提及过一次此方法
链接:http://blog.csdn.net/nash_/article/details/8199357
在a到b和函数组成的矩形的范围内,随机投N个点,落到绿色阴影点的个数为M个,对于此图来说便可以容易得知积分的值(绿色阴影)为(M/N)*矩形面积。
代码清单:
- public class JiFen {
- public static void main(String[] args){
- int N = 1000000;
- int count = 0;
- for(int i = 0; i < N; i++){
- double x = Math.random();
- double y = Math.random();
- if(f(x) >= y)
- count++;
- }
- System.out.println((double)count/N);
- }
- private static double f(double x) {
- return x*x;
- }
- }
public class JiFen {public static void main(String[] args){int N = 1000000;int count = 0;for(int i = 0; i < N; i++){double x = Math.random();double y = Math.random();if(f(x) >= y)count++;}System.out.println((double)count/N);}private static double f(double x) {return x*x;}}输出:0.333302
2.另一种蒙特卡洛法
第一种方法视乎情况比较特殊,如果是积分形式如下图:
对于普通情况,如果用第一种算法,就要判断随机点是投在了x轴的上方还是下方,对于矩形的选取还要分f(a),f(b)是否同号,以及f(a),f(b)的绝对值的大小,比较麻烦。于是产生了另一种投点法:在a到b的范围内随机生成N个点x1~xn,则积分的值为(f(x1) + f(x2) + ...+ f(xn)) * (b-a)/m。
代码清单:
- public class JiFen_toudian2 {
- public static void main(String[] args){
- double a = 0;
- double b = 1;
- double area = getArea(a,b);
- System.out.println(area);
- }
- public static double getArea(double a, double b){
- int sign = 1;//正负号标志位
- if(a > b){
- double t = a;
- a = b;
- b = t;
- sign = -1;
- }
- int N = 10000;
- double sum = 0;
- for(int i = 0; i < N; i++){
- double x = a + (b-a)*Math.random();//随机生成1个在(a,b)范围内的点
- sum += f(x);
- }
- return (sum * (b-a)/N) * sign;
- }
- private static double f(double x) {
- return x*x;
- }
- }
public class JiFen_toudian2 {public static void main(String[] args){double a = 0;double b = 1;double area = getArea(a,b);System.out.println(area);}public static double getArea(double a, double b){int sign = 1;//正负号标志位if(a > b){double t = a;a = b;b = t;sign = -1;}int N = 10000;double sum = 0;for(int i = 0; i < N; i++){double x = a + (b-a)*Math.random();//随机生成1个在(a,b)范围内的点sum += f(x);}return (sum * (b-a)/N) * sign; }private static double f(double x) {return x*x;}}输出:0.33966325465503505
3.定义求积分法
回忆一下最初是怎么求积分的,是把一块面积分解成N个小矩形,然后求面积和,最后求极限。我们就利用这种方式来实现它,但我们的N毕竟有限,为了结果更准确,把求矩形面积改成求梯形面积(当然矩形也是可以的),如下图:
把(a,b)分成N等分,积分值等于S1+S2+....+Sn,其中Si = (f(xi) + f(x(i+1))) * (b-a)/n / 2(矩形面积公式)
有了之前的基础,就可以比较容易的写程序了。
代码清单:
- public class JiFen3 {
- /**
- * @param args
- */
- public static void main(String[] args) {
- double a;
- double b;
- double y;
- a = 0;
- b = 1;
- y = getArea(a, b);
- System.out.println(y);
- }
- static double f(double x){
- return x*x;
- }
- static double getArea(double a, double b){
- int sign = 1;
- if(a > b){
- double t = a;
- a = b;
- b = t;
- sign = -1;
- }
- double h;
- double x;
- double sum = 0;
- int n = 10000;
- h = Math.abs(a - b)/n;
- x = a;
- for(int i = 0; i < n; i++){
- sum += f(x) + f(x + h);
- x = x + h;
- }
- return sum * h / 2 * sign;
- }
- }
public class JiFen3 {/** * @param args */public static void main(String[] args) {double a;double b;double y;a = 0;b = 1;y = getArea(a, b);System.out.println(y);}static double f(double x){return x*x;}static double getArea(double a, double b){int sign = 1;if(a > b){double t = a;a = b;b = t;sign = -1;}double h;double x;double sum = 0;int n = 10000;h = Math.abs(a - b)/n;x = a;for(int i = 0; i < n; i++){sum += f(x) + f(x + h);x = x + h;}return sum * h / 2 * sign;}}输出:0.3333333349999429
4.变步长梯形求积分法
用定义求积分法,要确定积分的误差是很难的,我们无法找到一个正好的N值符合我们要求的误差值,所以就需对定义法进行改进,改进的方式就是把原来固定的步长改为变化的步长,利用二分法,如下图:
图4-1
图4-2
图4-3
。
。
。
我们要分到什么时候呢? 分到 | 后一个面积和 - 前一个面积和 | < 规定误差 时。这样我们就达到了精确的目的。
代码清单:
- public class Jifen_bianchang {
- static double e = 0.00001;// 误差
- public static void main(String[] args) {
- double a = 0;// 积分下限
- double b = 1;// 积分上限
- double area = getArea(a, b);
- System.out.println(area);
- }
- public static double getArea(double a, double b) {
- int sign = 1;// 正负标志位
- if (a > b) {
- double t = a;
- a = b;
- b = t;
- sign = -1;
- }
- double s1 = 0;// 前一个面积和
- double s2 = 0;// 后一个面积和
- double h = b - a;
- s2 = getOneArea(a, b, h);
- for (int i = 2; Math.abs(s1 - s2) > e; i *= 2) {
- double t = h / i;// 每个梯形高
- double sum = 0;
- double x = a;
- for (int j = 0; j < i; j++) {// 求梯形和
- sum += getOneArea(x, x + t, t);
- x = x + t;
- }
- s1 = s2;
- s2 = sum;
- }
- return sign * s2;
- }
- public static double getOneArea(double a, double b, double h) {
- return (f(a) + f(b)) * h / 2;
- }
- public static double f(double x) {
- return x * x;
- }
- }
public class Jifen_bianchang {static double e = 0.00001;// 误差public static void main(String[] args) {double a = 0;// 积分下限double b = 1;// 积分上限double area = getArea(a, b);System.out.println(area);}public static double getArea(double a, double b) {int sign = 1;// 正负标志位if (a > b) {double t = a;a = b;b = t;sign = -1;}double s1 = 0;// 前一个面积和double s2 = 0;// 后一个面积和double h = b - a;s2 = getOneArea(a, b, h);for (int i = 2; Math.abs(s1 - s2) > e; i *= 2) {double t = h / i;// 每个梯形高double sum = 0;double x = a;for (int j = 0; j < i; j++) {// 求梯形和sum += getOneArea(x, x + t, t);x = x + t;}s1 = s2;s2 = sum;}return sign * s2;}public static double getOneArea(double a, double b, double h) {return (f(a) + f(b)) * h / 2;}public static double f(double x) {return x * x;}}
输出:0.33333587646484375
积分算法(二) (未完待续)
积分算法(三) (未完待续)
积分算法(四) (未完待续)
==================================================================================================
作者:nash_ 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/nash_/article/details/8560759
===================================================================================================
0 0
- 〖数学算法〗积分算法(一)
- 〖数学算法〗积分算法(一)
- 〖数学算法〗积分算法(一)
- 算法(一)---数学基础知识
- 【算法】算法中的趣味数学(一)
- 【工程数学】若干种解定积分的算法
- SPH算法简介(一): 数学基础
- SPH算法简介(一): 数学基础
- 数学建模算法总结(一)
- 〖数学算法〗逆矩阵算法
- 〖数学算法〗逆矩阵算法
- 数学建模算法 一 简述(1)蒙特卡洛算法
- LSD SLAM算法分析(一):算法数学基础
- 算法心经.数学的应用.积分的应用
- 数学基础一(Euclid算法)
- 算法竞赛中常见的数学(一):Fibonacci数列
- 算法竞赛入门经典数学篇实用小结(一)
- 数据结构与算法分析(一) —— 数学基础
- txt文档秘密
- c# 字符串处理
- 【算法导论学习-015】数组中选择第i小元素(Selection in expected linear time)
- STL vector中的erase方法(26)
- unity3d插件Daikon Forge GUI 中文教程-4-基础控件Checkbox和dropdownlis的使用
- 〖数学算法〗积分算法(一)
- Android中UI界面控制方式介绍与使用
- 数组,字典,集合的关系
- Populating Next Right Pointers in Each Node
- ~这些年,我们一起学过的java~07~我的十二生肖点歌版2048横空出世啦!!!~
- hdu 1202
- hadoop调度器
- hdu 1222
- ZOJ-1283