Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek

©2026 mgr Jerzy Wałaszek

obrazek

Interpolacja

Interpolacja  funkcjami sklejanymi

SPIS TREŚCI REMANENT
Podrozdziały
 

Algorytm

Interpolacja funkcjami sklejanymi (ang. spline interpolation) polega na przybliżaniu wartości interpolowanej funkcji za pomocą kawałków wielomianów niskiego stopnia (np. sześciennych) zdefiniowanych na poszczególnych podprzedziałach (segmentach) przedziału interpolacji. Jeśli wielomian jest funkcją liniową, otrzymujemy interpolację za pomocą łamanej, co opisuje wcześniejszy rozdział.

Angielska nazwa spline nawiązuje do tzw. krzywek, które dawniej były używane przez inżynierów do rysowania dowolnych krzywych na rysunkach technicznych (w przemyśle okrętowym, lotniczym i motoryzacyjnym).


Zestaw krzywek rysunkowych

Na przykład, jeśli mamy dziesięć węzłów funkcji w przedziale interpolacji, to zamiast dopasowywać do nich wszystkich pojedynczy wielomian dziewiątego stopnia, dopasowujemy dziewięć funkcji sześciennych do kolejnych par węzłów. W takiej interpolacji zwykle otrzymuje się lepsze przybliżenie wartości funkcji (przy odpowiednim rozkładzie węzłów) oraz unika się zjawiska Rungego, które pojawia się przy interpolacji wielomianami wysokich stopni.

Przykład

Przyjrzyjmy się sposobom konstruowania funkcji sklejanych. Załóżmy, że w przedziale <XS;XE> (XS - początek przedziału [X START], XE - koniec przedziału interpolacji [X END]) dla funkcji y = f(x) mamy 4 różne węzły, które dzielą ten przedział na trzy segmenty 0...2 (jak pokazano poniżej):


\[\begin{aligned}
&\text{Węzły:} \\
&v_0 = (x_0, y_0) \\
&v_1 = (x_1, y_1) \\
&v_2 = (x_2, y_2) \\
&v_3 = (x_3, y_3) \\
&\text{Segmenty:} \\
&s_0 \to \langle x_0; x_1 \rangle \\
&s_1 \to \langle x_1; x_2 \rangle \\
&s_2 \to \langle x_2; x_3 \rangle
\end{aligned}\]

Dla każdego segmentu definiujemy osobny wielomian sześcienny \(S_i (x)\) (zwany również wielomianem kubicznym):

\[\begin{array}{l}
S_0(x) = a_0 + b_0(x - x_0) + c_0(x - x_0)^2 + d_0(x - x_0)^3 \\
S_1(x) = a_1 + b_1(x - x_1) + c_1(x - x_1)^2 + d_1(x - x_1)^3 \\
S_2(x) = a_2 + b_2(x - x_2) + c_2(x - x_2)^2 + d_2(x - x_2)^3
\end{array}\]

\(a_i\), \(b_i\), \(c_i\) oraz \(d_i\) : \({i = 0,1,2}\) to współczynniki wielomianu sześciennego, które dla każdego segmentu \(s_i\) mogą być inne i należy je wyznaczyć. \(x_0\), \( x_1\) i \(x_2\) to współrzędne \(x\) początków segmentów \(s_0\), \( s_1\) i \(s_2\). Aby wyznaczyć współczynniki wielomianów sześciennych \(S_0(x)\), \(S_1(x)\) i \(S_2(x)\), musimy wykonać kilka założeń.

1. W węźle początkowym i końcowym każdego segmentu przypisany do niego wielomian sześcienny musi mieć wartość równą współrzędnej \(y\) tego węzła:

\[\begin{array}{l}
s_0:\left\{ \begin{array}{l} S_0(x_0) = y_0 \\ S_0(x_1) = y_1 \end{array} \right. \\
s_1:\left\{ \begin{array}{l} S_1(x_1) = y_1 \\ S_1(x_2) = y_2 \end{array} \right. \\
s_2:\left\{ \begin{array}{l} S_2(x_2) = y_2 \\ S_2(x_3) = y_3 \end{array} \right.
\end{array}\]

2. Aby wielomiany sześcienne gładko przechodziły jeden w następny na styku segmentów, ich pierwsze pochodne muszą być równe w tych węzłach:

\[\begin{array}{l}
s_0|s_1: S'_0(x_1) = S'_1(x_1) \\
s_1|s_2: S'_1(x_2) = S'_2(x_2)
\end{array}\]

3. To samo dla drugich pochodnych:

\[\begin{array}{l}
s_0|s_1: S''_0(x_1) = S''_1(x_1) \\
s_1|s_2: S''_1(x_2) = S''_2(x_2)
\end{array}\]

4. Dodatkowo zakładamy, iż druga pochodna wielomianu sześciennego na początku pierwszego segmentu i na końcu ostatniego segmentu ma wartość 0. Taki dobór warunków definiuje tzw. naturalną kubiczną funkcję sklejaną (ang. natural cubic spline). Zapewnia to otrzymanie najgładszej krzywej interpolacyjnej, co eliminuje nienaturalne wygięcia na końcach przedziału interpolacji.

\[\begin{array}{l}
|s_0: S''_0(x_0) = 0 \\
s_2|: S''_2(x_3) = 0
\end{array}\]

Założenia te pozwolą nam ułożyć odpowiednią ilość równań liniowych do wyznaczenia współczynników. W równaniach tych niewiadomymi będą współczynniki \(a_i\), \(b_i\), \(c_i\) oraz \(d_i\) : \({i = 0,1,2}\), natomiast wartości wyliczone ze współrzędnych węzłów będą stanowiły wiadome elementy (współczynniki oraz wyrazy wolne) w naszym układzie równań. Współczynników jest 12, zatem musimy mieć 12 równań. Wprowadzone założenia dadzą nam właśnie te 12 równań.

Rozpiszmy te równania.

Z punktu 1:

\[\left\{ \begin{array}{l}
a_0 + b_0(x_0 - x_0) + c_0(x_0 - x_0)^2 + d_0(x_0 - x_0)^3 = y_0 \\
a_0 + b_0(x_1 - x_0) + c_0(x_1 - x_0)^2 + d_0(x_1 - x_0)^3 = y_1 \\
a_1 + b_1(x_1 - x_1) + c_1(x_1 - x_1)^2 + d_1(x_1 - x_1)^3 = y_1 \\
a_1 + b_1(x_2 - x_1) + c_1(x_2 - x_1)^2 + d_1(x_2 - x_1)^3 = y_2 \\
a_2 + b_2(x_2 - x_2) + c_2(x_2 - x_2)^2 + d_2(x_2 - x_2)^3 = y_2 \\
a_2 + b_2(x_3 - x_2) + c_2(x_3 - x_2)^2 + d_2(x_3 - x_2)^3 = y_3
\end{array} \right.\]

Upraszczamy:

\[\left\{ \begin{array}{l}
a_0 = y_0 \\
a_0 + b_0(x_1 - x_0) + c_0(x_1 - x_0)^2 + d_0(x_1 - x_0)^3 = y_1 \\
a_1 = y_1 \\
a_1 + b_1(x_2 - x_1) + c_1(x_2 - x_1)^2 + d_1(x_2 - x_1)^3 = y_2 \\
a_2 = y_2 \\
a_2 + b_2(x_3 - x_2) + c_2(x_3 - x_2)^2 + d_2(x_3 - x_2)^3 = y_3
\end{array} \right.\]

Z punktu 2.

\[\begin{array}{l}
S_i(x) = a_i + b_i(x - x_i) + c_i(x - x_i)^2 + d_i(x - x_i)^3 \\
S'_i(x) = b_i + 2c_i(x - x_i) + 3d_i(x - x_i)^2 \\
S''_i(x) = 2c_i + 6d_i(x - x_i)
\end{array}\]
\[\begin{array}{l}
\left\{ \begin{array}{l}
b_0 + 2c_0(x_1 - x_0) + 3d_0(x_1 - x_0)^2 = b_1 \\
b_1 + 2c_1(x_2 - x_1) + 3d_1(x_2 - x_1)^2 = b_2
\end{array} \right. \\
\left\{ \begin{array}{l}
b_0 + 2c_0(x_1 - x_0) + 3d_0(x_1 - x_0)^2 - b_1 = 0 \\
b_1 + 2c_1(x_2 - x_1) + 3d_1(x_2 - x_1)^2 - b_2 = 0
\end{array} \right.
\end{array}\]

Z punktu 3.

\[\begin{array}{l}
\left\{ \begin{array}{l}
2c_0 + 6d_0(x_1 - x_0) = 2c_1 \\
2c_1 + 6d_1(x_2 - x_1) = 2c_2
\end{array} \right. \\
\left\{ \begin{array}{l}
2c_0 + 6d_0(x_1 - x_0) - 2c_1 = 0 \\
2c_1 + 6d_1(x_2 - x_1) - 2c_2 = 0
\end{array} \right.
\end{array}\]

Z punktu 4.

\[\left\{ \begin{array}{l}
2c_0 = 0 \\
2c_2 + 6d_2(x_3 - x_2) = 0
\end{array} \right.\]

Zbieramy równania w jeden układ równań. Niewiadomymi są tu współczynniki \(a \dots d\). Współrzędne węzłów są współczynnikami równań (czyli na odwrót, dlatego zapiszemy elementy odwrotnie):

\[\left\{ \begin{array}{l}
a_0 = y_0 \\
a_0 + (x_1 - x_0)b_0 + (x_1 - x_0)^2 c_0 + (x_1 - x_0)^3 d_0 = y_1 \\
a_1 = y_1 \\
a_1 + (x_2 - x_1)b_1 + (x_2 - x_1)^2 c_1 + (x_2 - x_1)^3 d_1 = y_2 \\
a_2 = y_2 \\
a_2 + (x_3 - x_2)b_2 + (x_3 - x_2)^2 c_2 + (x_3 - x_2)^3 d_2 = y_3 \\
b_0 + 2(x_1 - x_0)c_0 + 3(x_1 - x_0)^2 d_0 - b_1 = 0 \\
b_1 + 2(x_2 - x_1)c_1 + 3(x_2 - x_1)^2 d_1 - b_2 = 0 \\
2c_0 + 6(x_1 - x_0)d_0 - 2c_1 = 0 \\
2c_1 + 6(x_2 - x_1)d_1 - 2c_2 = 0 \\
2c_0 = 0 \\
2c_2 + 6(x_3 - x_2)d_2 = 0
\end{array} \right.\]

Dla uproszczenia wprowadźmy:

\[\begin{array}{l}
h_1 = x_1 - x_0 \\
h_2 = x_2 - x_1 \\
h_3 = x_3 - x_2
\end{array}\]

Po podstawieniu otrzymujemy prostszy układ równań:

\[\left\{ \begin{array}{l}
a_0 = y_0 \\
a_0 + h_1 b_0 + h_1^2 c_0 + h_1^3 d_0 = y_1 \\
a_1 = y_1 \\
a_1 + h_2 b_1 + h_2^2 c_1 + h_2^3 d_1 = y_2 \\
a_2 = y_2 \\
a_2 + h_3 b_2 + h_3^2 c_2 + h_3^3 d_2 = y_3 \\
b_0 + 2h_1 c_0 + 3h_1^2 d_0 - b_1 = 0 \\
b_1 + 2h_2 c_1 + 3h_2^2 d_1 - b_2 = 0 \\
2c_0 + 6h_1 d_0 - 2c_1 = 0 \\
2c_1 + 6h_2 d_1 - 2c_2 = 0 \\
2c_0 = 0 \\
2c_2 + 6h_3 d_2 = 0
\end{array} \right.\]

Teraz zapiszmy układ równań w postaci macierzowej:

\[\left[ \begin{array}{rrrrrrrrrrrr}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & h_1 & h_1^2 & h_1^3 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & h_2 & h_2^2 & h_2^3 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & h_3 & h_3^2 & h_3^3 \\
0 & 1 & 2h_1 & 3h_1^2 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 2h_2 & 3h_2^2 & 0 & -1 & 0 & 0 \\
0 & 0 & 2 & 6h_1 & 0 & 0 & -2 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 2 & 6h_2 & 0 & 0 & -2 & 0 \\
0 & 0 & 2 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 2 & 6h_3
\end{array} \right] \times \left[ \begin{array}{r}
a_0 \\ b_0 \\ c_0 \\ d_0 \\ a_1 \\ b_1 \\ c_1 \\ d_1 \\ a_2 \\ b_2 \\ c_2 \\ d_2
\end{array} \right] = \left[ \begin{array}{r}
y_0 \\ y_1 \\ y_1 \\ y_2 \\ y_2 \\ y_3 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0
\end{array} \right]\]

Układ równań rozwiązujemy jednym z wcześniej podanych algorytmów, np. eliminacją Gaussa-Crouta. Otrzymujemy współczynniki wielomianów kubicznych dla każdego segmentu.

Interpolacja dla danego x jest dwuetapowa:

Etap I: mając x znajdujemy segment przedziału interpolacji, w którym x się znajduje:

\[x_i \leqslant x \leqslant x_{i+1}\]

Jeśli segmenty są równej długości dx, to

\[i = \left\lfloor \dfrac{x - x_0}{dx} \right\rfloor\]

Jeśli segmenty mają różną długość, to do znalezienia właściwego segmentu można użyć wyszukiwania liniowego lub lepiej binarnego.

Etap II: mając numer segmentu i otrzymujemy dostęp do współczynników wielomianu kubicznego Si(x). Wielomian ten wykorzystujemy do aproksymacji funkcji f(x) w segmencie si:

\[\begin{array}{l}
f(x) \approx S_i(x) \\
f(x) \approx a_i + b_i(x - x_i) + c_i(x - x_i)^2 + d_i(x - x_i)^3 \\
f(x) \approx a_i + (x - x_i)\left( b_i + (x - x_i)\left( c_i + (x - x_i)d_i \right) \right)
\end{array}\]

do podrozdziału  do strony 

Przykładowa implementacja

Program interpoluje funkcję:

  \[y = \sin(x); x \in \left\langle -\dfrac{\pi}{2}; \dfrac{\pi}{2} \right\rangle\]

Przedział interpolacji: <-π/2;π/2>. W przedziale program generuje NN równoodległych współrzędnych x, wylicza dla nich współrzędną y wg przepisu funkcji i dostaje współrzędne NN węzłów interpolacyjnych.  Następnie wypełnia macierz współczynników i wyrazów wolnych na podstawie wartości x i y współrzędnych węzłów, po czym rozwiązuje układ równań  metodą eliminacji Gaussa-Crouta, otrzymując macierz współczynników wielomianów kubicznych. Na koniec generuje N punktów pseudolosowych w przedziale interpolacji i wylicza dla nich wartość interpolowaną funkcji f(x). Wyniki są porównywane z wartością funkcji.

C++
// Aproksymacja sklejana
// (C)2026 mgr Jerzy Wałaszek
// Metody numeryczne 0077
//---------------------------

#include <iostream>
#include <windows.h>
#include <iomanip>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

// Definicje stałych
//------------------

// Przedział interpolacji
// od XS do XE
const double XS = -M_PI / 2;
const double XE =  M_PI / 2;
// Ilość węzłów interpolacji
const int NN = 10;
// Ilość punktów interpolowanych
const int  N = 10;
// Szerokość segmentu
const double DX = (XE-XS)/(NN-1);
// Przyrównanie do zera
const double EPS = 1e-12;
// Tablice
//--------

// Współrzędne węzłów
double nx[NN];
double ny[NN];
// Współczynniki wielomianów
// w kolejnych segmentach
double A[NN-1][4];

// Funkcje
//--------

// Funkcja interpolowana
//----------------------
double f(double x)
{
  return sin(x);
}

// Zwraca wartość pseudolosową
// w przedziale [0;1)
//----------------------------
double random()
{
  return rand() /
         ((double)RAND_MAX + 1);
}

// Wyznacza węzły interpolacji
//----------------------------
void set_nodes(void)
{
  int i;

  // wyliczamy NN punktów x,y
  for(i = 0; i < NN; i++)
  {
    nx[i] = XS + i * DX;
    ny[i] = f(nx[i]);
  }
}

// Funkcja wylicza współczynniki
// dla wielomianów kubicznych.
// Współczynniki są w tablicy
// A[NN-1][4]. Współczynniki
// są czwórkami: a b c d dla
// kolejnych wielomianów.
// Zwraca true, gdy operacja
// się powiedzie.
bool set_a(void)
{
  // Najpierw ustawiamy macierz
  // rozszerzoną układu równań
  int n = 4 * (NN - 1); // wiersze
  double AB[n][n+1];
  int i,j;
  // Zerowanie macierzy AB
  for(i = 0; i < n; i++)
    for(j = 0; j <= n; j++)
      AB[i][j] = 0;

  // Wiersze z punktu 1 (wartości)
  int row = 0;
  for(i = 0; i < NN - 1; i++)
  {
    // Początek segmentu i
    AB[row][i*4] = 1; // a_i
    AB[row][n] = ny[i];
    row++;

    // Koniec segmentu i
    AB[row][i*4] = 1;          // a_i
    AB[row][i*4+1] = DX;       // b_i
    AB[row][i*4+2] = DX*DX;    // c_i
    AB[row][i*4+3] = DX*DX*DX; // d_i
    AB[row][n] = ny[i+1];
    row++;
  }

  // Wiersze z punktu 2 (pochodne S')
  for(i = 0; i < NN - 2; i++)
  {
    AB[row][i*4+1] = 1;      //  b_i
    AB[row][i*4+2] = 2*DX;   //  c_i
    AB[row][i*4+3] = 3*DX*DX;//  d_i
    AB[row][(i+1)*4+1] = -1; // -b_{i+1}
    row++;
  }

  // Wiersze z punktu 3 (pochodne S'')
  for(i = 0; i < NN - 2; i++)
  {
    AB[row][i*4+2] = 2;      // 2c_i
    AB[row][i*4+3] = 6*DX;   // 6*DX*d_i
    AB[row][(i+1)*4+2] = -2; // -2c_{i+1}
    row++;
  }

  // Wiersze z punktu 4 (brzegi)
  AB[row][2] = 2; // 2c_0 = 0
  row++;

  int last = NN - 2;
  AB[row][last*4+2] = 2;    // 2c_{last}
  AB[row][last*4+3] = 6*DX; // 6*DX*d_{last}
  row++;

  // Eliminacja Gaussa
  int k;
  for(i = 0; i < n; i++)
  {
    // Szukanie elementu osiowego
    for(j = i + 1; j < n; j++)
    {
      if(fabs(AB[j][i]) >
         fabs(AB[i][i]))
      {
        for(k = i; k <= n; k++)
        {
          double tmp = AB[i][k];
          AB[i][k] = AB[j][k];
          AB[j][k] = tmp;
        }
      }
    }

    // Sprawdzenie osobliwosci
    if(fabs(AB[i][i]) < EPS)
      return false;

    // Zerowanie pod przekątną
    for(j = i + 1; j < n; j++)
    {
      double factor =
        AB[j][i] / AB[i][i];
      for(k = i; k <= n; k++)
        AB[j][k] -=
          factor * AB[i][k];
    }
  }

  // Postępowanie wsteczne
  double X[n];
  for(i = n - 1; i >= 0; i--)
  {
    double sum = 0;
    for(j = i + 1; j < n; j++)
      sum += AB[i][j] * X[j];
    X[i] = (AB[i][n] - sum) /
           AB[i][i];
  }

  // Przepisanie do tablicy A
  for(i = 0; i < NN - 1; i++)
  {
    A[i][0] = X[i*4];   // a
    A[i][1] = X[i*4+1]; // b
    A[i][2] = X[i*4+2]; // c
    A[i][3] = X[i*4+3]; // d
  }

  return true;
}

// Funkcja zwraca numer
// segmentu dla x
int find_s(double x)
{
  return floor((x - XS) / DX);
}

// Wylicza wartość S_i(x)
//-----------------------
double f_i(double x)
{
  int i = find_s(x);
  double dx = x - nx[i];

  // Schemat Hornera
  return A[i][0] + dx * (
         A[i][1] + dx * (
         A[i][2] + dx *
         A[i][3]));
}

// Program główny

int main()
{
  int i;

  SetConsoleOutputCP(CP_UTF8);
  SetConsoleCP(CP_UTF8);

  cout << setprecision(4)
       << fixed;

  // Inicjujemy generator
  // pseudolosowy
  srand(time(nullptr));

  // Generujemy węzły
  set_nodes();

  // Obliczamy współczynniki
  if(set_a())
  {
    cout << "Interpolacja sklejana\n"
            "---------------------\n\n";

    // Generujemy N punktów x,
    // liczymy dla nich y
    // i wyświetlamy wynik
    double x,y;
    for(i = 0; i < N; i++)
    {
      x = XS + random() * (XE - XS);
      y = f_i(x);
      cout << "x = "
           << setw(7) << x
           << ", f(x) = "
           << setw(7) << f(x)
           << ", interpolacja f(x) = "
           << setw(7) << y
           << endl;
    }
  }
  else
    cout << "Błąd w obliczeniach\n";

  cout << endl;
  system("pause");
  return 0;
}
Wynik:
Interpolacja sklejana
---------------------

x = -0.0394, f(x) = -0.0394, interpolacja f(x) = -0.0394
x =  0.5146, f(x) =  0.4921, interpolacja f(x) =  0.4922
x = -0.8775, f(x) = -0.7692, interpolacja f(x) = -0.7692
x = -0.8499, f(x) = -0.7512, interpolacja f(x) = -0.7511
x =  1.1111, f(x) =  0.8962, interpolacja f(x) =  0.8977
x = -0.1182, f(x) = -0.1179, interpolacja f(x) = -0.1179
x = -0.3359, f(x) = -0.3297, interpolacja f(x) = -0.3297
x = -0.8531, f(x) = -0.7533, interpolacja f(x) = -0.7532
x =  0.4591, f(x) =  0.4432, interpolacja f(x) =  0.4433
x =  0.6380, f(x) =  0.5956, interpolacja f(x) =  0.5953
Python (dodatek)
# Aproksymacja sklejana
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0077
#---------------------------

from math import sin, floor, pi
from random import uniform

# Definicje stałych
#------------------

# Przedział interpolacji
# od XS do XE
XS = -pi / 2
XE =  pi / 2
# Ilość węzłów interpolacji
NN = 10
# Ilość punktów interpolowanych
N = 10
# Szerokość segmentu
DX = (XE - XS) / (NN - 1)
# Przyrównanie do zera
EPS = 1e-12

# Tablice
#--------

# Współrzędne węzłów
nx = [0] * NN
ny = [0] * NN
# Współczynniki wielomianów
# w kolejnych segmentach
a = [[0] * 4 for _ in range(NN - 1)]

# Funkcje
#--------

# Funkcja interpolowana
#----------------------
def f(x):
    return sin(x)

# Wyznacza węzły interpolacji
#----------------------------
def set_nodes():
    # wyliczamy NN punktów x,y
    for i in  range(NN):
        nx[i] = XS + i * DX
        ny[i] = f(nx[i])

# Funkcja wylicza współczynniki
# dla wielomianów kubicznych.
# Współczynniki są w tablicy
# A[NN-1][4]. Współczynniki
# są czwórkami: a b c d dla
# kolejnych wielomianów.
# Zwraca true, gdy operacja
# się powiedzie.
def set_a():
    # Najpierw ustawiamy macierz
    # rozszerzoną układu równań
    n = 4 * (NN - 1) # wiersze
    ab = [[0] * (n + 1)
          for _ in range(n)]

    # Wiersze z punktu 1 (wartości)
    row = 0
    for i in range(NN - 1):
        # Początek segmentu i
        ab[row][i*4] = 1  # a_i
        ab[row][n] = ny[i]
        row += 1
        # Koniec segmentu i
        ab[row][i*4]   = 1        # a_i
        ab[row][i*4+1] = DX       # b_i
        ab[row][i*4+2] = DX*DX    # c_i
        ab[row][i*4+3] = DX*DX*DX # d_i
        ab[row][n] = ny[i+1]
        row += 1

    # Wiersze z punktu 2 (pochodne S')
    for i in range(NN - 2):
        ab[row][i*4+1] = 1       #  b_i
        ab[row][i*4+2] = 2*DX    #  c_i
        ab[row][i*4+3] = 3*DX*DX #  d_i
        ab[row][(i+1)*4+1] = -1  # -b_{i+1}
        row += 1

    # Wiersze z punktu 3 (pochodne S'')
    for i in range(NN - 2):
        ab[row][i*4+2] = 2      # 2c_i
        ab[row][i*4+3] = 6*DX   # 6*DX*d_i
        ab[row][(i+1)*4+2] = -2 # -2c_{i+1}
        row += 1

    # Wiersze z punktu 4 (brzegi)
    ab[row][2] = 2 # 2c_0 = 0
    row +=1

    last = NN - 2
    ab[row][last*4+2] = 2    # 2c_{last}
    ab[row][last*4+3] = 6*DX # 6*DX*d_{last}
    row += 1

    # Eliminacja Gaussa
    for i in range(n):
        # Szukanie elementu osiowego
        for j in range(i + 1, n):
            if (abs(ab[j][i]) >
               abs(ab[i][i])):
                for k in range(i, n + 1):
                    ab[i][k], ab[j][k] = \
                    ab[j][k], ab[i][k]
        # Sprawdzenie osobliwosci
        if abs(ab[i][i]) < EPS:
            return False
        # Zerowanie pod przekątną
        for j in range(i + 1, n):
            factor = ab[j][i] / ab[i][i]
            for k in range(i, n + 1):
                ab[j][k] -= (factor *
                             ab[i][k])
    # Postępowanie wsteczne
    x = [0] * n
    for i in reversed(range(n)):
        sum_val = (sum(ab[i][j] * x[j]
            for j in range(i + 1, n)))
        x[i] = ((ab[i][n] - sum_val) /
                 ab[i][i])
    # Przepisanie do tablicy a
    for i in range(NN - 1):
        a[i][0] = x[i*4]   # a
        a[i][1] = x[i*4+1] # b
        a[i][2] = x[i*4+2] # c
        a[i][3] = x[i*4+3] # d
    return True

# Funkcja zwraca numer
# segmentu dla x
def find_s(x):
    return floor((x - XS) / DX)

# Wylicza wartość S_i(x)
#-----------------------
def f_i(x):
    i = find_s(x)
    dx = x - nx[i]

    # Schemat Hornera
    return a[i][0] + dx * (
           a[i][1] + dx * (
           a[i][2] + dx *
           a[i][3]))

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

# Generujemy węzły
set_nodes()

# Obliczamy współczynniki
if set_a():
    print("Interpolacja sklejana\n"
          "---------------------\n")
    # Generujemy N punktów x,
    # liczymy dla nich y
    # i wyświetlamy wynik
    for i in range(N):
        x = uniform(XS,XE)
        y = f_i(x)
        print(f"x = {x:7.4f}, "
              f"f(x) = {f(x):7.4f}, "
              f"interpolacja f(x) = "
              f"{y:7.4f}")

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.

Informacje dodatkowe.