改进的欧拉(Euler)公式
欧拉公式
y n + 1 = y n + h f ( x n , y n ) n ∈ N \begin{array}{l}y_{n+1}=y_n+hf\left(x_n,y_n\right)n\in N\end{array} yn+1=yn+hf(xn,yn)n∈N
梯形公式
y
n
+
1
=
y
n
+
h
2
[
f
(
x
n
,
y
n
)
+
f
(
x
n
+
1
,
y
n
+
1
)
]
,
n
∈
N
\begin{array}{l}y_{n+1}=y_n+\frac h2\lbrack f\left(x_n,y_n\right)+f(x_{n+1},y_{n+1})], n\in N\end{array}
yn+1=yn+2h[f(xn,yn)+f(xn+1,yn+1)],n∈N
该方法综合l欧拉方法和梯形方法,欧拉方法是一个显式的算法,它的计算量少,但是精度低;而梯形方法虽然可以提高精度,但是它是一种隐式算法,需要借助不断地迭代求解,它的计算量相对较大。
改进的欧拉(Euler)公式综合二者的优势,先用欧拉方法求得一个初步的近似值
y
‾
n
+
1
\overline y_{n+1}
yn+1称之为预报值,预报值的精度不高,我们用它直接代替梯形公式右端的
y
n
+
1
\ y_{n+1}
yn+1得到校正值
y
n
+
1
\ y_{n+1}
yn+1,建立预报-校正系统,又称为改进的欧拉(Euler)公式.
嵌套格式
算法框图
变量说明
x
0
,
y
0
x_0,y_0
x0,y0:初值条件
h
h
h:步长
N
N
N:步数
研究对象
程序运行结果截图
数据分析
数据统计表格
y
n
为
计
算
值
,
f
(
x
n
)
为
精
确
值
,
R
(
x
n
)
为
余
项
值
,
可
以
理
解
为
误
差
.
(
所
有
数
据
来
自
上
图
)
y_n为计算值,f(x_n)为精确值,R(x_n)为余项值,可以理解为误差.(所有数据来自上图)
yn为计算值,f(xn)为精确值,R(xn)为余项值,可以理解为误差.(所有数据来自上图)
数据绘图
蓝色线为计算值:
y
n
y_n
yn;黄色线为准确值:
f
(
x
n
)
f(x_n)
f(xn)
Source Codes(完整代码见github)
public static List<List<Double>> getEstimates(double x0,double y0,double h,int N) {
List<List<Double>> result = new ArrayList<>();
List<Double> xi = new ArrayList<>();
List<Double> yi = new ArrayList<>();
List<Double> reals = new ArrayList<>();
List<Double> miscount = new ArrayList<>();
double x1,y1,yp,yc,real,mis,K1,K2,K3,K4;
for (int i = 0 ; i < N ; i++ ) {
x1 = x0 + h;
yp = y0 + h*f(x0,y0);
yc = y0 + h*f(x1,yp);
y1 = (yp + yc)/2;
real = getReal(x0);
mis = Math.abs(real - y1);
xi.add(x1);
yi.add(y1);
reals.add(real);
miscount.add(mis);
x0 = x1;
y0 = y1;
}
result.add(xi);
result.add(yi);
result.add(reals);
result.add(miscount);
return result;
}
四阶龙格-库塔(Runge-Kutta)方法
研究对象
算法框图
变量说明
x
0
,
y
0
x_0,y_0
x0,y0:初值条件
h
h
h:步长
N
N
N:步数
程序运行截图
数据分析
数据统计表格
y
n
为
计
算
值
,
f
(
x
n
)
为
精
确
值
,
R
(
x
n
)
为
余
项
值
,
可
以
理
解
为
误
差
.
(
所
有
数
据
来
自
上
图
)
y_n为计算值,f(x_n)为精确值,R(x_n)为余项值,可以理解为误差.(所有数据来自上图)
yn为计算值,f(xn)为精确值,R(xn)为余项值,可以理解为误差.(所有数据来自上图)
数据绘图
蓝色线为计算值:
y
n
y_n
yn;黄色线为准确值:
f
(
x
n
)
f(x_n)
f(xn);灰色线为余项值:
R
(
x
n
)
.
R(x_n).
R(xn).
Source Codes(完整代码见github)
public static List<List<Double>> getEstimates(double x0,double y0,double h,int N) {
List<List<Double>> result = new ArrayList<>();
List<Double> xi = new ArrayList<>();
List<Double> yi = new ArrayList<>();
List<Double> reals = new ArrayList<>();
List<Double> miscount = new ArrayList<>();
double x1,y1,yp,yc,real,mis,K1,K2,K3,K4;
for (int i = 0 ; i < N ; i++ ) {
K1 = f(x0,y0);
K2 = f(x0+h/2,y0+h*K1/2);
K3 = f(x0+h/2,y0+h*K2/2);
K4 = f(x1,y0+h*K3);
y1 = y0 + h*(K1 + 2*K2 + 2*K3 + K4)/6;
real = getReal(x0);
mis = Math.abs(real - y1);
xi.add(x1);
yi.add(y1);
reals.add(real);
miscount.add(mis);
x0 = x1;
y0 = y1;
}
result.add(xi);
result.add(yi);
result.add(reals);
result.add(miscount);
return result;
}
小结
初值问题他们都有一个共同的特点,采用步进式,即是过程中顺着节点的排列顺序一步一步的向前推进。通过本次实验,虽然说这种方式理论上是可以得到任何精度要求下的数据值,但是,随之带来的是巨大的计算量。
步长
h
h
h是决定性因素,步长小,精度高,但是前进速度慢;步长大,前进速度快,精度较差。所以在实际应用过程中,对步长的选择就显得十分重要。