龙格库塔法比欧拉法有更高的精度。
Runge-Kutta Ansatz
Δ y ( t ) = a ∗ f ( t , y ) + b ∗ f ( t + α h , y + β f ) ( a , b , α , β i s f r e e p a r a m e t e r s ) = a f + b f + b ( f t α + f y f β ) h : = h f + h 2 2 ( f t + f y f ) \Delta y(t)=a*f(t,y)+b*f(t+\alpha h, y+\beta f) \quad (a, b, \alpha, \beta \quad is free parameters)\\ = af+bf+b(f_t\alpha+f_yf\beta)h\\ :=hf+\frac{h^2}{2}(f_t+f_yf) Δy(t)=a∗f(t,y)+b∗f(t+αh,y+βf)(a,b,α,βisfreeparameters)=af+bf+b(ftα+fyfβ)h:=hf+2h2(ft+fyf)
其中 a + b = h a+b=h a+b=h, α b = h 2 \alpha b=\frac{h}{2} αb=2h, β b = h 2 \beta b=\frac{h}{2} βb=2h。
时间复杂度
O ( h 4 ) O(h^4) O(h4)。
C++ 实现 4 4 4 阶 RK
输入参数
类似欧拉法。
f ′ ( x ) f'(x) f′(x) 函数
类似欧拉法,采用外部函数的方式,定义好接口,每个具体问题具体实现。由于 RK 需要计算 k 1 , k 2 , k 3 , k 4 k_1, k_2, k_3, k_4 k1,k2,k3,k4,因此 RK 的函数原型对应如下。
//x,y 表示对应的坐标
//h 为步长
//k 为返回值,一个4大小的数组
void df(double x, double y, double h, double k[]);
主框架
参考欧拉法实现。
#include <iostream>
using namespace std;
/*f'(x)函数*/
//x,y 表示对应的坐标
//h 为步长
//k 为返回值,一个4大小的数组
void df(double x, double y, double h, double k[]);
int main() {
//变量定义
double x0, y0;//起点坐标
double xn;//终点坐标
int step;//迭代次数
cout<<"Enter Initial Condition x0:";
cin>>x0;
cout<<"Enter Initial Condition y0:";
cin>>y0;
cout<<"Enter calculation point xn:";
cin>>xn;
cout<<"Enter number of steps:";
cin>>step;
double delta;//x的增量
delta=(xn-x0)/step;
/* Runge Kutta Method */
double yn;
double k[4];
cout<<"Step:\tx0\ty0\t\tyn\n";
cout<<"-----------\n";
for (int i=1; i<=step; i++) {
df(x0, y0, delta, k);
yn=y0+(k[0]+2*k[1]+2*k[2]+k[3])/6;
cout<<i<<":\t"<<x0<<"\t"<<y0<<"\t"<<yn<<"\n";
x0=x0+delta;
y0=yn;
}
//结果输出
cout<<"\nValue of y at x= "<<xn<<" is " <<yn<<"\n";
return 0;
}
样例
样例 1
给定 d y d x = y 2 − x 2 y 2 + x 2 \frac{dy}{dx}=\frac{y^2-x^2}{y^2+x^2} dxdy=y2+x2y2−x2,初始条件为 y ( 0 ) = 1 y(0)=1 y(0)=1,计算 y ( 0.6 ) y(0.6) y(0.6) 的值,用 3 3 3 步。
f ′ ( x ) f'(x) f′(x) 函数实现
static double df1(double x, double y) {
return (y*y-x*x)/(y*y+x*x);
}
//x,y 表示对应的坐标
//h 为步长
//k 为返回值,一个4大小的数组
void df(double x, double y, double h, double k[]) {
k[0]=h*df1(x, y);
k[1]=h*df1(x+h/2, y+k[0]/2);
k[2]=h*df1(x+h/2, y+k[1]/2);
k[3]=h*df1(x+h, y+k[2]);
}
编译
测试环境为 Win10+MinGW,使用 g++ 编译器。
g++ -g -o RK.exe main.cpp df1.cpp