最近在写软件,需要用到积分。我们采用多个矩形累加的方法,很容易实现积分的功能,但是这个方法有一个问题:我们不知道把a~b之间分成多少份,也就是不知道n取多少。如果n太小,计算结果精度较低,n太大,则计算量太大,且过高的精度在工程上也没有意义。
这里我们采用自适应的方式,让程序自己选择n的大小。我们首先定义两个要积分的函数f1和f2。
double f1(double x)
{
return 1/x;
}
double f2(double x)
{
return 1/(x * x);
}
下面是积分函数:
4个参数的意义:
a:积分的起点;
b:积分的终点;
n:从a到b,一共分成n份。这个n是另一个函数指定的。
myFun: 函数指针,可以用来指定对f1还是f2进行积分。
//从a到b的积分,但不一定精确
//第三个参数是一个函数指针,申明的时候一定要注意函数名后面带上参数列表
//这时,函数名就可以被当做参数传递到函数中
double jifen(double a, double b, int n, double (*myFun)(double))
{
//把被积分的区域a~b等分成n块。dx就是每一块的宽度。
//在数学上,并没有要求每一块的宽度相等。这里为了简单起见,采取等分
double dx = (b - a) /n;
double sum = 0;
double x; //具体的x的位置
for(int i = 0; i < n ; i++)
{
x = a + dx * i; //动态更新x的值
//myFun相当于C#中的delegation (委托)
//直接使用形参中的函数指针调用不同的函数,例如f1和f2
//矩形法计算一小块矩形的面积,并进行累加
sum += myFun(x) * dx;
}
return sum;
}
在编写完基本的积分函数之后,我们开始编写能决定jifen()中n的值的函数jifen2()。这是这段程序的关键所在。
在积分的定义上,并没有规定把a和b之间的距离进行等分,只规定每一份之间的距离都是无穷小 (dx->0)。为了简便起见,我们把a和b之间的距离进行等分。
我们采用的思路是:如果把a和b之间的距离等分成n份进行计算积分值,得到一个结果r1;如果把a和b之间的距离等分成10 * n份进行计算积分值,得到一个结果r2。随着n的增大,积分值距离真正的精确值越来越近,提高的幅度也越来越小。如果r1和r2之间的差距太大,则需要继续增大n的值。如果r1和r2之间的差距 < 0.1%,则我们认为r1和r2都是比较准确的值。r1和r2之间的差距很小时,r1和r2都与真实值很接近,它们与真实值之间的差距也很小。据此,我们写下如下程序:我们要求两个结果之间的差距 < 0.1%。
//最大误差为0.1%的积分
//第三个参数是一个函数指针,申明的时候一定要注意函数名后面带上参数列表
//这时,函数名就可以被当做参数传递到函数中