Cpp 在计算中如何处理大数?

问题描述

我有一个代码,它尝试使用梯形规则的方法(参见 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。将完全以这种方式生成的xx原始方式进行比较。

x = (x0-x1)/2 + ((k - n/2)*delta_x)


打印出计算出的准确值以加深理解。

printf("x:%a y:%a\n",x0+(k*delta_x),func(x0+(k*delta_x)));