Пожалуйста, напечатайте также последний x0
, вы увидите, что итерация никогда не останавливается на b
. Представление с плавающей запятой h
и увеличение x0
на h
редко бывают точными, так что итерация сама по себе не "достигнет" значения b
, она остановится на чуть меньше b+h
.
h returned x returned y
------------------------------------------------
0.1 (3.0000000000000018, 2.0855312227119374)
0.01 (3.0099999999999794, 2.1671997121516187)
0.001 (3.0009999999997796, 2.093630295729702 )
0.0001 (3.000000000002, 2.08553671291036 )
1e-05 (3.0000000000131024, 2.0855367130274134)
Вы можете исправить это, предварительно вычислив число шагов или исправив последний шаг
def f(x,y):
return 2*x**2-4*x+y
def RK4(x0,y0,xf,h):
while x0 < xf:
if x0+h > xf: h=xf-x0
k1 = h*f(x0,y0)
k2 = h*f(x0+0.5*h,y0+0.5*k1)
k3 = h*f(x0+0.5*h,y0+0.5*k2)
k4 = h*f(x0+h,y0+k3)
y0+=(k1+2*k2+2*k3+k4)/6
x0+=h
return x0,y0
b=3
for k in range (1,6): h=10**-k; print h, RK4(1,0.7182818,b,h)
, который дает желаемые результаты
h returned (x, y)
-----------------------------------
0.1 (3.0, 2.0855312227119236)
0.01 (3.0, 2.0855367122312707)
0.001 (3.0, 2.085536712901802 )
0.0001 (3.0, 2.0855367128941893)
1e-05 (3.0, 2.0855367129214737)
Как было объявлено, вы можете предварительно вычислить число N
шагов и убедиться, что N*h=xf-x0
. Для этого замените
while x0 < xf:
if x0+h > xf: h=xf-x0
с
Dx = float(xf-x0); N = int(0.5+Dx/h); h = Dx/N
for _ in range(N):
, где вы все еще можете наблюдать накопление ошибок с плавающей запятой в x0
,
0.1 (3.0000000000000018, 2.0855312227119374)
0.01 (2.9999999999999796, 2.0855367122311055)
0.001 (2.9999999999997797, 2.085536712900021 )
0.0001 (3.000000000002, 2.08553671291036 )
1e-05 (3.0000000000131024, 2.0855367130274134)