Spring-_-Bear 的 CSDN 博客导航

式(1)是四阶龙格 - 库塔格式的一种常用经典格式:

{ y n + 1 = y n + h 6 ( K 1 + 2 K 2 + 2 K 3 + K 4 ) K 1 = f ( x n , y n ) K 2 = f ( x n + 1 2 , y n + h 2 K 1 ) K 3 = f ( x n + 1 2 , y n + h 2 K 2 ) K 4 = f ( x n + 1 , y n + h K 3 ) (1) \begin{cases} y_{n+1}=y_{n}+\frac{h}{6}(K_{1}+2K_{2}+2K_{3}+K_{4})\\ K_{1}=f(x_{n},y_{n})\\ K_{2}=f(x_{n+\frac{1}{2}},y_{n}+\frac{h}{2}K_{1})\\ K_{3}=f(x_{n+\frac{1}{2}},y_{n}+\frac{h}{2}K_{2})\\ K_{4}=f(x_{n+1},y_{n}+hK_{3}) \end{cases} \tag1 yn+1=yn+6h(K1+2K2+2K3+K4)K1=f(xn,yn)K2=f(xn+21,yn+2hK1)K3=f(xn+21,yn+2hK2)K4=f(xn+1,yn+hK3)(1)

经典的龙格 - 库塔格式(1)每一步需要 4 次计算函数值 f f f,可以直接验证它具有四阶精度,不过其论证极其繁琐,此处从略。下图描述了四阶经典的龙格 - 库塔方法。

在这里插入图片描述

例:设取步长 h = 0.2,从 x = 0 到 x = 1 用四阶经典格式(1)解决以下常微分方程的初值问题。

{ y ′ = y − 2 x y ( 0 < x < 1 ) y ( 0 ) = 1 \begin{cases} y'=y-\frac{2x}{y} (0 < x < 1)\\ y(0)=1 \end{cases} {y=yy2x(0<x<1)y(0)=1

解:这里四阶经典格式(1)中 K1,K2,K3,K4 的具体形式是

K 1 = y n − 2 x n y n K_{1}=y_{n}-\frac{2x_{n}}{y_{n}} K1=ynyn2xn

K 2 = y n + h 2 K 1 − 2 x n + h y n + h 2 K 1 K_{2}=y_{n}+\frac{h}{2}K_{1}-\frac{2x_{n}+h}{y_{n}+\frac{h}{2}K_{1}} K2=yn+2hK1yn+2hK12xn+h

K 3 = y n + h 2 K 2 − 2 x n + h y n + h 2 K 2 K_{3}=y_{n}+\frac{h}{2}K_{2}-\frac{2x_{n}+h}{y_{n}+\frac{h}{2}K_{2}} K3=yn+2hK2yn+2hK22xn+h

K 4 = y n + h K 3 − 2 ( x n + h ) y n + h K 3 K_{4}=y_{n}+hK_{3}-\frac{2(x_{n}+h)}{y_{n}+hK_{3}} K4=yn+hK3yn+hK32(xn+h)

下表中记录了计算结果,其中 y ( x n ) y(x_{n}) y(xn) 仍表示准确解。

xn yn y(xn)
0.2 1.1832 1.1832
0.4 1.3417 1.3416
0.6 1.4833 1.4832
0.8 1.6125 1.6125
1.0 1.7321 1.7321

运行示例:

在这里插入图片描述

程序源码:

#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

/**
 * 欧拉格式中的 x,y 的函数关系式,即 f(xn,yn)
 */
double f(double x, double y)
{
    return y - 2 * x / y;
}

/**
 * 实际函数解析式
 */
double f1(double x)
{
    return sqrt(1 + 2 * x);
}

int main(void)
{
    double x0, y0;
    cout << "请输入初值:";
    cin >> x0 >> y0;

    double h;
    cout << "请输入步长:";
    cin >> h;

    int N;
    cout << "请输入步数:";
    cin >> N;

    // 输出提示信息
    cout << "\t" << setw(10) << "xn"
        << "\t" << setw(10) << "yn"
        << "\t" << setw(10) << "y(xn)" << endl;

    for (int i = 1; i <= N; i++)
    {
        // 离散点
        double x1 = x0 + h;
        // 求斜率
        double K1 = f(x0, y0);
        double K2 = f(x0 + h / 2, y0 + h / 2 * K1);
        double K3 = f(x0 + h / 2, y0 + h / 2 * K2);
        double K4 = f(x1, y0 + h * K3);
        // 求新值
        double y1 = y0 + h / 6 * (K1 + 2 * K2 + 2 * K3 + K4);
        // 输出本次步进后的离散点数据
        cout << i << "\t" << setw(10) << x1 << "\t" << setw(10) << y1 << "\t" << setw(10) << f1(x1) << endl;

        x0 = x1;
        y0 = y1;
    }

    return 0;
}

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐