数值微分C++实现

  • 问题描述


取h=0.1时用Euler法,改进Euler法,Rung-Kutta方法求其数值解并与精确解进行比较。

输入:求解区间,初值,数值解个数

输出:数值解

  • 基本公式

改进欧拉公式:

 四阶龙格—库塔方法:



  • 流程图

改进的欧拉方程 :                             四阶龙格—库塔方法:



  • 算法实现
#include <iostream>
#include <math.h>
#include <iomanip>

using namespace std;

//定义系数C
double C;
//保存生成的节点横坐标
double dataX[100];
//保存生成的节点准确的纵坐标
double dataY[100];
//保存Euler的解
double dataE[100];
//保存改进Euler的解
double dataIE[100];
//保存Rung-Kutta方法求其数值解
double dataRK[100];
//定义原函数
double function(double x,double y);
//定义导函数
double derivative(double x);
//分割区间
void devide(double a,double b,int N,double y);
//定义用欧拉方法求解的函数
void Euler(double a,double b,double n);
//定义用改进欧拉方法求解的函数
void improveEuler(double a,double b,double n);
//定义四阶龙格-库塔方法求解的函数
void RungKutta(double a,double b,double n);
//打印表格
void printTable(double n);

int main()
{
    //定义左右区间端点
    double a ,b;
    //定义初值
    double y;
    //定义数值解的个数
    int n;
    cout<<"请输入求解区间:";
    cin>>a>>b;
    cout<<"请输入初值:";
    cin>>y;
    cout<<"请输入求解个数:";
    cin>>n;
    //算出原函数的系数C
    C = (pow(y,2) - 2*a - 1)/(pow(M_E,2*a));
    devide(a,b,n,y);
    Euler(a,b,n);
    improveEuler(a,b,n);
    RungKutta(a,b,n);
    printTable(n);
    return 0;
}
//定义原函数
double function(double x)
{
    return sqrt(C*pow(M_E,2*x) + 2*x + 1);
}
//定义导函数
double derivative(double x,double y)
{
    return y - 2*x/y;
}

//分割区间
void devide(double a,double b,int N,double y)
{
    double x = a;
    double dX = (b - a) /(N) ;
    //x=0时,特殊处理
    dataX[0] = x;
    dataY[0] = y;
    for(int i=1;i<=N;i++)
    {
        x = a + i * dX;
        dataX[i] = x;
        dataY[i] = function(x);
    }
}
//定义用欧拉方法求解的函数
void Euler(double a,double b,double n)
{
    dataE[0] = dataY[0];
    for(int i=0;i<n;i++)
    {
        double value = dataE[i] + ((b-a)/n)*derivative(dataX[i],dataE[i]);
        dataE[i+1] = value;
    }
}
//定义用改进欧拉方法求解的函数
void improveEuler(double a,double b,double n)
{
    dataIE[0] = dataY[0];
    for(int i=0;i<n;i++)
    {
        //计算向前差商
        double Yp = dataIE[i] + ((b-a)/n)*derivative(dataX[i],dataIE[i]);
        //计算向后差商
        double Yc = dataIE[i] + ((b-a)/n)*derivative(dataX[i+1],Yp);
        dataIE[i+1] = 0.5 * (Yp + Yc);
    }
}
//定义四阶龙格-库塔方法求解的函数
void RungKutta(double a,double b,double n)
{
    dataRK[0] = dataY[0];
    for(int i=0;i<n;i++)
    {
        double K1 = derivative(dataX[i],dataRK[i]);
        double middleX = (dataX[i] + dataX[i+1]) * 0.5;
        double K2 = derivative(middleX,dataRK[i]+ 0.5 * ((b - a)/n) * K1);
        double K3 = derivative(middleX,dataRK[i]+ 0.5 * ((b - a)/n) * K2);
        double K4 = derivative(dataX[i+1],dataRK[i] + ((b - a)/n) * K3);
        dataRK[i+1] = dataRK[i] + (1.0/6) * ((b - a)/n) * (K1 + 2 * K2 + 2 * K3 + K4);
    }
}
//打印表格
void printTable(double n)
{
    cout<<"------------------------------------------------------------------"<<endl;
    cout<<"x        "<<"y(4阶龙格) "<<"y(改进)  "<<"y(欧拉)  "<<"y(精确)    "<<endl;
    for(int i=1;i<=n;i++)
    {
        cout<<setiosflags(ios::fixed);
        cout<<setprecision(6)<<dataX[i]<<" "<<dataRK[i]<<" "<<dataIE[i]<<" "<<dataE[i]<<" "<<dataY[i]<<endl;
    }
}

  • 运行截图





数值微分法是一种利用数值计算方法对函数进行微分的技术。在实际应用中,数值微分法常用于处理无法解析求导的函数,或者对实验数据进行处理和分析。其中,直线拟合法是一种常见的数值微分方法。 在C++中,实现直线拟合法可以通过以下步骤: 1. 定义x和y数组,存储函数的自变量和因变量数据。 2. 计算x和y的平均值,分别记为x_mean和y_mean。 3. 计算x和y的标准差,分别记为x_stddev和y_stddev。 4. 定义斜率k和截距b,通过以下公式计算: k = sum((x[i] - x_mean) * (y[i] - y_mean)) / sum((x[i] - x_mean)^2) b = y_mean - k * x_mean 5. 将k和b作为直线的参数,即可完成直线拟合。 以下是C++代码示例: ```c++ #include <iostream> #include <cmath> using namespace std; int main() { // 定义x和y数组 double x = {1, 2, 3, 4, 5}; double y = {1, 4, 9, 16, 25}; // 计算平均值 double x_mean = 0; double y_mean = 0; for (int i = 0; i < 5; i++) { x_mean += x[i]; y_mean += y[i]; } x_mean /= 5; y_mean /= 5; // 计算标准差 double x_stddev = 0; double y_stddev = 0; for (int i = 0; i < 5; i++) { x_stddev += pow(x[i] - x_mean, 2); y_stddev += pow(y[i] - y_mean, 2); } x_stddev /= 5; y_stddev /= 5; x_stddev = sqrt(x_stddev); y_stddev = sqrt(y_stddev); // 计算斜率和截距 double k = 0; double b = 0; for (int i = 0; i < 5; i++) { k += (x[i] - x_mean) * (y[i] - y_mean); } k /= pow(x_stddev, 2); b = y_mean - k * x_mean; // 输出结果 cout << "斜率 k = " << k << endl; cout << "截距 b = " << b << endl; return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值