问题描述
我有一个代码,它尝试使用梯形规则的方法(参见 Trapezoid method 中的公式)以数值方式求解给定区间内函数的积分,现在,对于函数 sin(x)区间[-pi/2.0,pi/2.0],积分等待为零。
在这种情况下,我将分区数 'n' 设为 4。问题是,当我有 20 个小数位的 pi 时,它为零,14 个小数位时它是 8.72e^(-17),然后有 11 个小数位,它是零,有 8 个小数位是 8.72e^(-17),有 3 个小数位是零。我的意思是,对于 pi 的不同近似值,积分为零或接近零的数字,但它没有明显的趋势。
如果您能帮助我理解为什么会发生这种情况,我将不胜感激。 (我确实在 Dev-C++ 中运行过它)。
#include <iostream>
#include <math.h>
using namespace std;
#define pi 3.14159265358979323846
//Pi: 3.14159265358979323846
double func(double x){
return sin(x);
}
int main() {
double x0 = -pi/2.0,xf = pi/2.0;
int n = 4;
double delta_x = (xf-x0)/(n*1.0);
double sum = (func(x0)+func(xf))/2.0;
double integral;
for (int k = 1; k<n; k++){
// cout<<"func: "<<func(x0+(k*delta_x))<<" "<<"last sum: "<<sum<<endl;
sum = sum + func(x0+(k*delta_x));
// cout<<"func + last sum= "<<sum<<endl;
}
integral = delta_x*sum;
cout<<"The value for the integral is: "<<integral<<endl;
return 0;
}
解决方法
OP 正在将 y=sin(x)
从 -a
集成到 +a
。各种测试使用不同的 a
值,均接近 pi/2。
该方法使用接近 -1.0 的值的线性总和,从 0 到接近 1.0。
这个总和对最后一项的计算错误很敏感,因为最终的数学总和预计为 0.0。由于开始/结束 a
不同,错误也不同。
首先添加极端的 f = sin(f(k))
值会得到更稳定的结果。例如sum += sin(f(k=1))
,然后是 sum += sin(f(k=3))
,然后是 sum += sin(f(k=2))
而不是 k=1,2,3。特别是,术语 x=f(k=3)
的形成可能与其早期的 x=f(k=1)
术语的否定有所不同,从而进一步加剧了问题。
欢迎来到世界或数值分析。
如果代码全部使用 float
或全部使用 long double
,只是程度不同,则存在问题。
问题不是由于使用了不精确的 pi 值(精确值对于 FP 是不可能的,因为 pi 是无理数,所有有限的 FP 都是有理数)。
很大程度上是由于 x
的形成。可以尝试以下方法来形成约 0.0 对称的 x
。将完全以这种方式生成的x
与x
原始方式进行比较。
x = (x0-x1)/2 + ((k - n/2)*delta_x)
打印出计算出的准确值以加深理解。
printf("x:%a y:%a\n",x0+(k*delta_x),func(x0+(k*delta_x)));