Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz  

obrazek

Autor artykułu: mgr Jerzy Wałaszek

©2026 mgr Jerzy Wałaszek

obrazek

Równania różniczkowe

Metoda Rungego-Kutty

SPIS TREŚCI
Podrozdziały
 

Wstęp

Po metodzie Eulera (która jest metodą pierwszego rzędu), w analizie numerycznej równań różniczkowych zwyczajnych (ang. ODE Ordinary Differential Equations) stosuje się bardziej zaawansowane algorytmy. Zapewniają one znacznie wyższą dokładność i stabilność bez konieczności drastycznego zmniejszania odstępu \(h\).

Oto krótkie zestawienie metod rozwiązywania równań różniczkowych:

Metody jawne wyższych rzędów (Jednokrokowe)

To bezpośredni, naturalni następcy metody Eulera. Też liczą wartość w punkcie \(x + h\) na podstawie punktu poprzedniego, ale robią to z większą precyzją.

Metody adaptacyjne (Z automatycznym doborem kroku)

Metody niejawne (Dla równań sztywnych)

Niezbędne do rozwiązywania układów, w których procesy zachodzą w skrajnie różnych skalach czasowych (tzw. stiff equations), gdzie klasyczny Euler czy RK4 błyskawicznie "wylatują w nieskończoność".

Metody wielokrokowe (Pamiętające historię)

Zamiast liczyć wszystko od nowa w każdym kroku przy użyciu punktów próbnych (jak przy metodzie Rungego-Kutty), te metody wykorzystują wartości wyliczone w kilku poprzednich krokach.

Jak widzisz, temat jest bardzo rozległy i wymagałby osobnego artykułu. Tutaj opiszemy klasyczną metodę Rungego-Kutty czwartego rzędu (ang. Classical fourth-order Runge-Kutta method).

Krótka historia metody

Klasyczna metoda Rungego-Kutty nie została stworzona przez jednego uczonego, lecz jest efektem pracy dwóch wybitnych niemieckich matematyków na przełomie XIX i XX wieku. Podwaliny pod algorytm położył w 1895 roku Carl Runge. Zaproponował on rozbudowanie prostych metod numerycznych (takich jak metoda Eulera) o dodatkowe punkty próbne pomiędzy krokami obliczeniowymi, co miało drastycznie zwiększyć dokładność otrzymywanych wyników. Pomysł ten w 1901 roku udoskonalił i uogólnił Martin Kutta, formułując ostateczny, genialny wariant czwartego rzędu (znany dziś na całym świecie jako RK4).Opracowany przez nich algorytm okazał się tak potężny i stabilny, że ponad sto lat później — w erze superkomputerów — wciąż stanowi złoty standard i absolutną podstawę w fizyce komputerowej, inżynierii oraz symulacjach mechaniki nieba.


do podrozdziału  do strony 

Algorytm metody Rungego-Kutty

Rdzeń matematyczny RK4

W metodzie Rungego-Kutty zamiast jednej stycznej (jak w metodzie Eulera) liczymy cztery próbne współczynniki nachylenia \({(k_1, k_2, k_3, k_4)}\), a nowe \(y\) wyznaczamy jako średnią ważoną z tych czterech wartości.

Dla równania \({\frac{dy}{dx} = f(x,y)}\) i odstępu \(h\), algorytm przejścia do kolejnego punktu wygląda następująco:

  1. Współczynnik \(k_1\) – nachylenie na początku kroku (to jest dokładnie to, co robi metoda Eulera):
\[k_1=f(x,y)\]
  1. Współczynnik \(k_2\) – nachylenie w połowie kroku, przy użyciu wyliczonego \(k_1\):
\[k_2=f\left(x+\frac{h}{2},y+\frac{h}{2}\cdot k_1\right)\]
  1. Współczynnik \(k_3\) – ponowne nachylenie w połowie kroku, ale przy użyciu dokładniejszego współczynnika \(k_2\):
\[k_3=f\left(x+\frac{h}{2},y+\frac{h}{2}\cdot k_2\right)\]
  1. Współczynnik \(k_4\) – nachylenie na końcu kroku, przy użyciu \(k_3\):
\[k_4=f(x+h,y+h\cdot k_3)\]
  1. Ostateczne wyznaczenie nowego \(y\):
\[y_{nowe}=y+\frac{h}{6}\cdot (k_1+2k_2+2k_3+k_4)\]
  1. Przesunięcie \(x\) na kolejną pozycję:
\[x_{nowe}=x_{s}+c\cdot h\]

Algorytm metody RK4

Specyfikacja problemu

Dane wejściowe

\(x_s\) : współrzędna \(x\) punktu startowego; \({x_s \in \mathbb{R}}\).
\(x_k\) : współrzędna \(x\) punktu końcowego; \({x_k \in \mathbb{R},\;x_k > x_s}\).
\(y_s\) : współrzędna \(y\) punktu startowego; \({y_s \in \mathbb{R}}\).
\(h\) : odstęp punktów po osi \(x\); \({h \in \mathbb{R},\;h > 0}\).
\(f(x,y)\) : funkcja rzeczywista, która definiuje równanie różniczkowe

Dane wyjściowe

\(y\) : przybliżona wartość funkcji \(y(x)\) w punkcie końcowym \(x_k\); \({y \in \mathbb{R}}\).

Zmienne pomocnicze

\(x\) : bieżąca współrzędna \(x\); \({x \in \mathbb{R}}\).
\(c\) : numer kroku; \({c \in \mathbb{N}}\)
\(k_1,k_2,k_3,k_4\) : współczynniki próbne nachylenia; \({k_{1},k_{2},k_{3},k_{4}\in \mathbb{R}}\)

Lista kroków

K01: \(x \leftarrow x_s\) ; inicjujemy zmienne:
K02: \(y \leftarrow y_s\) ; x i y z warunku początkowego
K03: \(c \leftarrow 0\) ; numer kroku
K04: Pisz \(c,x,y\) ; wypisujemy wstępne współrzędne punktów
K05: Dopóki \(x < x_k\),
wykonuj kroki K06...K12
 
K06:   \(c \leftarrow c+1\) ; zwiększamy numer kroku
K07:   \(k_1\leftarrow f(x,y)\) ; pierwszy współczynnik próbny
K08:   \(k_2 \leftarrow f(x + \frac{h}{2},\; y + \frac{h}{2} \cdot k_1)\) ; drugi współczynnik próbny
K09:   \(k_3 \leftarrow f(x + \frac{h}{2},\; y + \frac{h}{2} \cdot k_2)\) ; trzeci współczynnik próbny
K10:   \(k_4 \leftarrow f(x + h,\; y + h \cdot k_3)\); ; czwarty współczynnik próbny
K11:   \(y \leftarrow y + \frac{h}{6} \cdot (k_1 + 2k_2 + 2k_3 + k_4)\) ; wzór RK4 na nowe y
K12:   \(x \leftarrow x_s + c \cdot h\) ; przesuwamy się na osi OX
K13:   Pisz \(c,x,y\) ; wypisujemy współrzędne punktów
K14: Zakończ  

do podrozdziału  do strony 

Przykład implementacji RK4

Poniższe programy rozwiązują równanie różniczkowe \({\frac{dy}{dx} = x + y}\) z warunkiem  początkowym \({y(0) = 1}\) na przedziale od \({x = 0}\) do \({x = 2{,}5}\). Jako odstęp \(h\) wybieramy \(0{,}125\) (taka liczba jest przez komputer pamiętana dokładnie bez błędu zaokrągleń zmiennoprzecinkowych). Wyjaśnienia są w komentarzach.

Dla porównania programy wyświetlają również wartość dokładną funkcji \(y(x)\). Rozwiązaniem analitycznym (dokładnym) równania różniczkowego \({\frac{dy}{dx} = x + y}\) z warunkiem początkowym \({y(0) = 1}\) jest funkcja:

\[
y(x)=2e^x - x - 1
\]

Porównaj wyniki z poprzednią metodą Eulera.

C++
// Równania różniczkowe
// metoda Rungego-Kutty
// Metody numeryczne 0086
// --------------------------
// (C)2026 mgr Jerzy Wałaszek

#include <windows.h>
#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

// Stałe
//------
// Przedział (start,koniec)
const double x_s = 0.000;
const double x_k = 2.500;
// Warunek początkowy
const double y_s = 1.000;
// Odstęp na osi OX
const double h   = 0.125;

// Funkcja prawej strony
// równania różniczkowego
//-----------------------
double f(double x,double y)
{
  return x + y;
}

// Funkcja wynikowa
// obliczona analitycznie
//-----------------------
double rf(double x)
{
  return 2 * exp(x) - x - 1;
}

// Wypisuje wyniki
//----------------
void pisz(int c, double x, double y)
{
  cout << setw(3) << c
  << ": x = " << setw(7) << x
  << "  y = " << setw(8) << y
  << "| dokładnie y = "
  << setw(8) << rf(x)
  << endl;
}

// Program główny
//---------------

int main()
{
  SetConsoleOutputCP(CP_UTF8);
  SetConsoleCP(CP_UTF8);

  cout << setprecision(5)
       << fixed;

  // inicjujemy zmienne
  double x = x_s;
  double y = y_s;
  double k1,k2,k3,k4;
  int    c = 0;

  cout << "Rozwiązywanie równania "
          "różniczkowego metodą "
          "Rungego-Kutty\n"
          "-----------------------"
          "---------------------"
          "-------------\n\n";
  pisz(c,x,y);
  // Metoda Rungego-Kutta
  while(x < x_k)
  {
    c++;
    k1 = f(x,y);
    k2 = f(x+h/2,y+h/2*k1);
    k3 = f(x+h/2,y+h/2*k2);
    k4 = f(x+h,y+h*k3);
    y  = y+h/6*(k1+2*k2+2*k3+k4);
    x = x_s + c * h;
    pisz(c,x,y);
  }
  cout << endl;
  system("pause");
  return 0;
}
Wynik:
Rozwiązywanie równania różniczkowego metodą Rungego-Kutty
---------------------------------------------------------

  0: x = 0.00000  y =  1.00000| dokładnie y =  1.00000
  1: x = 0.12500  y =  1.14130| dokładnie y =  1.14130
  2: x = 0.25000  y =  1.31805| dokładnie y =  1.31805
  3: x = 0.37500  y =  1.53498| dokładnie y =  1.53498
  4: x = 0.50000  y =  1.79744| dokładnie y =  1.79744
  5: x = 0.62500  y =  2.11149| dokładnie y =  2.11149
  6: x = 0.75000  y =  2.48399| dokładnie y =  2.48400
  7: x = 0.87500  y =  2.92274| dokładnie y =  2.92275
  8: x = 1.00000  y =  3.43655| dokładnie y =  3.43656
  9: x = 1.12500  y =  4.03542| dokładnie y =  4.03543
 10: x = 1.25000  y =  4.73067| dokładnie y =  4.73069
 11: x = 1.37500  y =  5.53513| dokładnie y =  5.53515
 12: x = 1.50000  y =  6.46335| dokładnie y =  6.46338
 13: x = 1.62500  y =  7.53181| dokładnie y =  7.53184
 14: x = 1.75000  y =  8.75917| dokładnie y =  8.75921
 15: x = 1.87500  y = 10.16659| dokładnie y = 10.16664
 16: x = 2.00000  y = 11.77806| dokładnie y = 11.77811
 17: x = 2.12500  y = 13.62073| dokładnie y = 13.62079
 18: x = 2.25000  y = 15.72539| dokładnie y = 15.72547
 19: x = 2.37500  y = 18.12693| dokładnie y = 18.12703
 20: x = 2.50000  y = 20.86488| dokładnie y = 20.86499
Python (dodatek)
# Równania różniczkowe
# metoda Rungego-Kutty
# Metody numeryczne 0086
# --------------------------
# (C)2026 mgr Jerzy Wałaszek

from math import exp

# Stałe
#------
# Przedział (start,koniec)
x_s = 0.0
x_k = 2.5
# Warunek początkowy
y_s = 1.0
# Odstęp na osi OX
h   = 0.125

# Funkcja prawej strony
# równania różniczkowego
#-----------------------
def f(x, y):
    return x + y

# Funkcja wynikowa
# obliczona analitycznie
#-----------------------
def rf(x):
    return 2 * exp(x) - x - 1

# Wypisuje wyniki
#----------------
def pisz(c, x, y):
    print(f"{c:3d}: x = {x:7.5f}    "
          f"y = {y:8.5f}| "
          f"dokładnie y = {rf(x):8.5f}")

# Program główny
#---------------

# inicjujemy zmienne
x = x_s
y = y_s
c = 0
print("Rozwiązywanie równania "
      "różniczkowego metodą "
      "Rungego-Kutty\n"
      "-----------------------"
      "---------------------"
      "-------------\n")
pisz(c, x, y)

# Metoda Rungego-Kutty
while x < x_k:
    c += 1
    k1 = f(x, y)
    k2 = f(x + h/2, y + h/2 * k1)
    k3 = f(x + h/2, y + h/2 * k2)
    k4 = f(x + h, y + h * k3)
    y  = y + h/6 * (k1 + 2*k2 + 2*k3 + k4)
    x = x_s + c * h
    pisz(c, x, y)

print()
input("Naciśnij Enter...")

do podrozdziału  do strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2026 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
W soboty i niedziele reklamy są wyłączane w całym serwisie.
Informacje dodatkowe.