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 liniowa

SPIS TREŚCI REMANENT
Podrozdziały
 

Algorytm

Zadaniem interpolacji jest znalezienie wartości pośrednich pomiędzy wartościami znanymi. Aby zrozumieć, jak to działa, załóżmy, że mamy do czynienia z pewną funkcją:

Załóżmy dalej, że udało nam się zmierzyć wartość tej funkcji w dwóch punktach: (x0,y0) i (x1,y1):

Łączymy te punkty odcinkiem:

Odcinek przybliża funkcję f(x) pomiędzy punktami (x0,y0) i (x1,y1). Załóżmy teraz, iż mamy pewne x, które leży pomiędzy x0 i x1. Chcemy znaleźć przybliżoną wartość funkcji f(x) dla tej współrzędnej x. W tym celu znajdziemy na odcinku punkt (x,y) o współrzędnej x:

Wykorzystamy tutaj geometrię. Utwórzmy dwa trójkąty prostokątne:

Zewnętrzny trójkąt mający boki a i b (a - podstawa, b - wysokość) oraz wewnętrzny z bokami c i d (c - podstawa, d - wysokość). Przeciwprostokątne tych trójkątów leżą na odcinku łączącym punkty (x0,y0) i (x1,y1). Zapiszmy wzory na długości tych boków:

Ponieważ trójkąty są podobne, możemy ułożyć proporcję:

W proporcji nieznana jest wartość d (wysokość trójkąta wewnętrznego), zatem liczymy ją:

Podstawiamy wzory na długości boków:

Otrzymujemy podstawowy wzór interpolacji liniowej:


do podrozdziału  do strony 

Przykłady implementacji

W pierwszym programie wykorzystamy otrzymany wzór interpolacyjny do wyznaczenia 10 wartości funkcji f(x) = sin(x) w przedziale domkniętym <0;π/2>. Wyjaśnienie znajdziesz w komentarzach w programie.

C++
// Interpolacja liniowa
// (C)2026 mgr Jerzy Wałaszek
// Metody numeryczne 0071
//---------------------------

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

using namespace std;

// Stałe
//------

// Liczba interpolowanych
// punktów
const int N = 10;

// Przedział interpolacji
// od XS do XE
const double XS = 0;
const double XE = M_PI / 2;

// Funkcja oblicza wartość
// interpolowanej funkcji
// na podstawie jej przepisu
//--------------------------
double f(double x)
{
  return sin(x);
}

// Funkcja oblicza
// wartość interpolowaną
//----------------------
double f_i(double x0,
           double y0,
           double x1,
           double y1,
           double x)
{
  return y0 + (y1 - y0) /
        (x1 - x0) * (x - x0);
}

// Funkcja zwraca wartość
// pseudolosową w przedziale <0,1)
//--------------------------------
double random()
{
  return rand() / ((double)RAND_MAX + 1);
}

// Program główny
//---------------
int main()
{
  SetConsoleOutputCP(CP_UTF8);
  SetConsoleCP(CP_UTF8);

  cout << setprecision(4)
       << fixed;

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

  // Generujemy tablicę
  // N współrzędnych x
  // w przedziale <XS,XE>
  double x[N], y[N];
  int i;
  for(i = 0; i < N; i++)
    x[i] = XS + random() * (XE - XS);

  // Punkty krańcowe
  double x0 = XS;
  double y0 = f(x0);
  double x1 = XE;
  double y1 = f(x1);

  // obliczamy współrzędne y
  for(i = 0; i < N; i++)
    y[i] = f_i(x0,y0,x1,y1,x[i]);

  // Wyświetlamy wyniki:
  cout << "Interpolacja liniowa\n"
          "--------------------\n\n";
  for(i = 0; i < N; i++)
    cout << "x = "
         << setw(7) << x[i]
         << ", f(x) = "
         << setw(7) << f(x[i])
         << ", interpolacja f(x) = "
         << setw(7) << y[i]
         << endl;

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

x =  1.0280, f(x) =  0.8563, interpolacja f(x) =  0.6544
x =  0.4897, f(x) =  0.4704, interpolacja f(x) =  0.3118
x =  0.6477, f(x) =  0.6034, interpolacja f(x) =  0.4124
x =  0.0000, f(x) =  0.0000, interpolacja f(x) =  0.0000
x =  1.1749, f(x) =  0.9226, interpolacja f(x) =  0.7480
x =  1.4669, f(x) =  0.9946, interpolacja f(x) =  0.9338
x =  1.0993, f(x) =  0.8909, interpolacja f(x) =  0.6999
x =  0.1452, f(x) =  0.1447, interpolacja f(x) =  0.0924
x =  0.5621, f(x) =  0.5329, interpolacja f(x) =  0.3578
x =  0.2935, f(x) =  0.2893, interpolacja f(x) =  0.1869
Python (dodatek)
# Interpolacja liniowa
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0071
#---------------------------

from math import sin,pi
from random import random

# Stałe
#------

# Liczba interpolowanych
# punktów
N = 10

# Przedział interpolacji
# od XS do XE
XS = 0
XE = pi / 2

# Funkcja oblicza wartość
# interpolowanej funkcji
# na podstawie jej przepisu
#--------------------------
def f(x):
    return sin(x)

# Funkcja oblicza
# wartość interpolowaną
#----------------------
def f_i(x0,y0,x1,y1,x):
    return (y0 + (y1 - y0) /
            (x1 - x0) * (x - x0))

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

# Punkty krańcowe
x0 = XS
y0 = f(x0)
x1 = XE
y1 = f(x1)

# Generujemy tablice
# N współrzędnych x
# w przedziale <XS,XE>
# oraz interpolowanych
# wartości funkcji f()
# dla współrzędnych x
x = []
y = []
for i in range(N):
    x.append(XS + random() * (XE - XS))
    y.append(f_i(x0,y0,x1,y1,x[i]))

# Wyświetlamy wyniki:
print("Interpolacja liniowa\n"
      "--------------------\n")
for i in range(N):
    print(f"x = {x[i]:7.4f}"
          f", f(x) = {f(x[i]):7.4f}"
          f", interpolacja f(x) = "
          f"{y[i]:7.4f}")

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

Gdy przeglądniesz wyniki, zauważysz iż wyznaczone wartości są obarczone błędami interpolacji (dla f(x) = sin(x) do 1/3 wartości f(x)). Dokładność można zwiększyć dodając w przedziale interpolacji nowe węzły interpolacyjne (węzeł interpolacyjny to punkt, w którym wartość funkcji zrównuje się z wartością interpolowaną):

W tym przypadku przedział <0;π/2> podzieliliśmy na dwa przedziały:

<x0;x1> = <0;π/4>
<x1;x2> = <π/4;π/2>

Obliczamy wartość funkcji na krańcach tych przedziałów i otrzymujemy:

y0 = sin(x0) = sin(0)
y1 = sin(x1) = sin(π/4)
y2 = sin(x2) = sin(π/2)

Dostajemy trzy węzły interpolacyjne:

P0 = (x0,y0)
P1 = (x1,y1)
P2 = (x2,y2)

Kolejne węzły interpolacyjne łączymy odcinkami i otrzymujemy łamaną, która lepiej przybliża przebieg funkcji niż pierwotny pojedynczy odcinek:

Prześledźmy algorytm interpolacji wielowęzłowej. Mamy pewną funkcję y = f(x):

Określamy przedział interpolacji: <xs;xe>, w którym będziemy interpolować wartości funkcji f(x) dla x z tego przedziału:

Przedział <xs;xe> dzielimy na nn równych segmentów:

Segmenty mają stałą długość dx:

Jeśli segmenty interpolacji mają stałą długość dx, to współrzędnych xi, i = 0,1,...,nn nie musimy wcale zapamiętywać, ponieważ można je łatwo wyliczyć na podstawie ich numeru:

Oczywiście, jeśli mamy interpolować wiele wartości funkcji f(x), to wyznaczone punkty xi zapamiętujemy, w celu przyspieszenia obliczeń.

Dla każdej współrzędnej xi, i = 0,1,...,nn musimy posiadać wartości funkcji yi = f(xi):

Otrzymujemy w ten sposób węzły interpolacyjne, które łączymy odcinkami i dostajemy łamaną, która przybliża przebieg funkcji:

Po tym etapie przygotowawczym jesteśmy gotowi do wykonania interpolacji. Mamy zatem pewne x ∈ <xs;xe>. Zaczynamy od znalezienia segmentu <xi;xi+1>, i = 0,1,...,nn-1, takiego że:

Jeśli punkty xi są rozłożone równomiernie w przedziale interpolacji, to numer i możemy wyliczyć korzystając z szerokości segmentu dx:

Mając numer segmentu, możemy obliczyć wartość interpolowaną funkcji dla argumentu x:

Kolejny program interpoluje liniowo funkcję y = sin(x) w przedziale domkniętym <-π;π>. Wykonuje on następujące operacje:

C++
// Interpolacja liniowa
// (C)2026 mgr Jerzy Wałaszek
// Metody numeryczne 0072
//---------------------------

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

using namespace std;

// Stałe
//------

// Liczba węzłów
// interpolacyjnych
const int NN = 50;

// Liczba punktów
// interpolowanych
const int N = 10;

// Krańce przedziału
// interpolacji
const double XS = -M_PI;
const double XE =  M_PI;

// Tablice współrzędnych
// węzłów interpolacji
double nx[NN+1], ny[NN+1];

// Szerokość segmentu
const double DX = (XE - XS) / NN;

// Interpolowana funkcja
//----------------------
double f(double x)
{
  return sin(x);
}

// Zwraca liczbę
// pseudolosową <0,1)
//-------------------
double random()
{
  return rand() /
         (double)(RAND_MAX + 1);
}

// Przygotowuje tablice
// nx[] i ny[]
//---------------------
void setnn()
{
  int i;
  for(i = 0; i <= NN; i++)
  {
    nx[i] = XS + i * DX;
    ny[i] = f(nx[i]);
  }
}

// Oblicza wartość
// interpolowaną
//----------------
double f_i(double x0,
           double y0,
           double x1,
           double y1,
           double x)
{
  return y0 + (y1 - y0) /
        (x1 - x0) * (x - x0);
}

// Program główny
//---------------
int main()
{
  SetConsoleOutputCP(CP_UTF8);
  SetConsoleCP(CP_UTF8);

  cout << setprecision(4)
       << fixed;

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

  // Przygotowujemy tablice
  // nx[] i ny[]
  setnn();

  // Generujemy tablicę
  // N współrzędnych x
  // w przedziale <XS,XE>
  double x[N], y[N];
  int i,j;

  for(j = 0; j < N; j++)
  {
    x[j] = XS + random() *
          (XE - XS);

    // Wyznaczamy segment
    i = floor((x[j] - XS) / DX);

    // Wartość interpolowana
    // funkcji
    y[j] = f_i(nx[i],ny[i],
               nx[i+1],ny[i+1],
               x[j]);
  }

  // Wyświetlamy wyniki:
  cout <<
  "Interpolacja liniowa\n"
  "--------------------\n\n";
  for(i = 0; i < N; i++)
    cout << "x = "
         << setw(7) << x[i]
         << ", f(x) = "
         << setw(7) << f(x[i])
         << ", interpolacja f(x) = "
         << setw(7) << y[i]
         << endl;

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

x =  0.6926, f(x) =  0.6385, interpolacja f(x) =  0.6373
x = -2.4900, f(x) = -0.6064, interpolacja f(x) = -0.6057
x =  3.0051, f(x) =  0.1361, interpolacja f(x) =  0.1360
x = -1.7673, f(x) = -0.9807, interpolacja f(x) = -0.9803
x =  0.7369, f(x) =  0.6720, interpolacja f(x) =  0.6714
x = -0.4732, f(x) = -0.4558, interpolacja f(x) = -0.4551
x = -0.5981, f(x) = -0.5630, interpolacja f(x) = -0.5623
x =  0.1419, f(x) =  0.1414, interpolacja f(x) =  0.1413
x =  1.2535, f(x) =  0.9501, interpolacja f(x) =  0.9499
x =  2.9176, f(x) =  0.2221, interpolacja f(x) =  0.2218

Zwróć uwagę, iż teraz wartości interpolowane lepiej zgadzają się z wartościami funkcji. Zwiększ liczbę węzłów interpolacji NN, np.  do 1000. Tego typu rozwiązania pozwalają obliczać wartości funkcji na podstawie jej znanych wartości.

Python (dodatek)
# Interpolacja liniowa
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0072
#---------------------------

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

# Stałe
#------

# Liczba węzłów
# interpolacyjnych
NN = 50

# Liczba punktów
# interpolowanych
N = 10

# Krańce przedziału
# interpolacji
XS = -pi
XE =  pi

# Tablice współrzędnych
# węzłów interpolacji
nx = []
ny = []

# Szerokość segmentu
DX = (XE - XS) / NN

# Interpolowana funkcja
#----------------------
def f(x):
    return sin(x)

# Przygotowuje tablice
# nx[] i ny[]
#---------------------
def setnn():
    for i in range(NN + 1):
        nx.append(XS + i * DX)
        ny.append(f(nx[i]))

# Oblicza wartość
# interpolowaną
#----------------
def f_i(x0, y0, x1, y1, x):
    return (y0 + (y1 - y0) /
           (x1 - x0) * (x - x0))

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

# Przygotowujemy tablice
# nx[] i ny[]
setnn()

# Generujemy tablicę
# N współrzędnych x
# w przedziale <XS,XE>
x = []
y = []

for j in range(N):
    x.append(XS + random() * (XE - XS))

    # Wyznaczamy segment
    i = int(floor((x[j] - XS) / DX))

    # Wartość interpolowana
    # funkcji
    y.append(f_i(nx[i],ny[i],
                 nx[i+1],ny[i+1],
                 x[j]))

# Wyświetlamy wyniki:
print("Interpolacja liniowa\n"
      "--------------------\n")
for i in range(N):
    print(f"x = {x[i]:7.4f}"
          f", f(x) = "
          f"{f(x[i]):7.4f}"
          f", interpolacja f(x) = "
          f"{y[i]:7.4f}")

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

Jeśli dane węzłów interpolacji pochodzą np. z czujników, to wcale nie muszą tworzyć węzłów równoodległych, ani nie muszą być uporządkowane. Algorytm interpolujący należy wtedy zmodyfikować.

Procedura jest następująca:

  1. Wczytujemy współrzędne węzłów jako pary współrzędnych (xi,yi) tworzących węzły interpolacji.
  2. Węzły interpolacji porządkujemy wg rosnących współrzędnych x.
  3. Pierwszy i ostatni węzeł interpolacji wyznaczają przedział interpolacji.
  4. Wczytujemy wartość x, dla której mamy znaleźć wartość interpolowaną.
  5. Mając x, szukamy podprzedziału <xi;xi+1> interpolacji, w który to x wpada: xi ≤ x ≤ xi+1. Jeśli węzłów jest niewiele, to wyszukiwać można liniowo, w przeciwnym razie można użyć np. wyszukiwania binarnego.
  6. Gdy przedział zostanie znaleziony, to na podstawie węzłów (xi,yi) i (xi+1,yi+1) obliczamy wartość interpolowaną ze wzoru interpolacyjnego.

Trzeci program działa wg powyższej procedury. Wyjaśnienia są w komentarzach.

C++
// Interpolacja liniowa
// (C)2026 mgr Jerzy Wałaszek
// Metody numeryczne 0073
//---------------------------

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

using namespace std;

// Stałe
//------

// Liczba segmentów
// interpolacyjnych
const int NN = 50;

// Liczba punktów
// interpolowanych
const int N = 10;

// Krańce przedziału
// interpolacji
const double XS = -M_PI;
const double XE =  M_PI;

// Tablice współrzędnych
// węzłów interpolacji
double nx[NN+1], ny[NN+1];

// Interpolowana funkcja
//----------------------
double f(double x)
{
  return sin(x);
}

// Zwraca liczbę
// pseudolosową <0,1)
//-------------------
double random()
{
  return rand() / (double)(RAND_MAX + 1);
}

// Funkcja porównująca dla
// qsort()
//------------------------
int cmp(const void * a,
        const void * b)
{
  double da = *(const double*)a;
  double db = *(const double*)b;
  if (da < db) return -1;
  if (da > db) return 1;
  return 0;
}

// Przygotowuje tablice nx[] i ny[]
//---------------------------------
void setnn()
{
  int i;

  // Dwa pierwsze punkty to węzły początkowy
  // i końcowy
  nx[0] = XS;
  nx[1] = XE;

  // Pozostałe punkty to węzły pośrednie
  for(i = 2; i <= NN; i++)
    nx[i] = XS + random() * (XE - XS);

  // Porządkujemy rosnąco
  // współrzędne x węzłów
  qsort((void *)nx,    // tablica
        (size_t)NN+1,  // ilość elem.
        sizeof(double),// rozmiar elem.
        cmp);          // funkcja porówn.

  // Teraz wyznaczamy współrzędne y dla
  // uporządkowanych współrzędnych x
  for(i = 0; i <= NN; i++)
    ny[i] = f(nx[i]);
}

// Oblicza wartość interpolowaną
//------------------------------
double f_i(double x0,
           double y0,
           double x1,
           double y1,
           double x)
{
  return y0 + (y1 - y0) /
        (x1 - x0) * (x - x0);
}

// Program główny
//---------------
int main()
{
  SetConsoleOutputCP(CP_UTF8);
  SetConsoleCP(CP_UTF8);

  cout << setprecision(4)
       << fixed;

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

  // Przygotowujemy tablice
  // nx[] i ny[]
  setnn();

  // Generujemy tablicę N współrzędnych x
  // do interpolowania w przedziale <XS,XE>
  double x[N], y[N];
  int i,j;

  for(j = 0; j < N; j++)
  {
    x[j] = XS + random() * (XE - XS);

    // Wyznaczamy segment, w którym
    // jest interpolowany punkt
    for(i = 0; nx[i] < x[j]; i++);

    i--;

    // interpolujemy
    y[j] = f_i(nx[i],ny[i],
               nx[i+1],ny[i+1],
               x[j]);
  }

  // Wyświetlamy wyniki:
  cout <<
  "Interpolacja liniowa\n"
  "--------------------\n\n";
  for(i = 0; i < N; i++)
    cout << "x = "
         << setw(7) << x[i]
         << ", f(x) = "
         << setw(7) << f(x[i])
         << ", interpolacja f(x) = "
         << setw(7) << y[i]
         << endl;

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

x =  1.2856, f(x) =  0.9596, interpolacja f(x) =  0.9590
x = -0.9119, f(x) = -0.7906, interpolacja f(x) = -0.7850
x = -0.5975, f(x) = -0.5625, interpolacja f(x) = -0.5621
x =  3.1103, f(x) =  0.0312, interpolacja f(x) =  0.0310
x =  2.2525, f(x) =  0.7765, interpolacja f(x) =  0.7762
x = -1.7463, f(x) = -0.9846, interpolacja f(x) = -0.9792
x =  0.6460, f(x) =  0.6020, interpolacja f(x) =  0.6006
x = -1.8863, f(x) = -0.9506, interpolacja f(x) = -0.9417
x =  0.3373, f(x) =  0.3309, interpolacja f(x) =  0.3218
x = -1.3839, f(x) = -0.9826, interpolacja f(x) = -0.9804
Python (dodatek)
# Interpolacja liniowa
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0073
#---------------------------

from random import random
from math import pi,sin

# Stałe
#------

# Liczba segmentów
# interpolacyjnych
NN = 50

# Liczba punktów
# interpolowanych
N = 10

# Krańce przedziału
# interpolacji
XS = -pi
XE =  pi

# Tablice współrzędnych
# węzłów interpolacji
nx = []
ny = []

# Interpolowana funkcja
#----------------------
def f(x):
    return sin(x)

# Przygotowuje tablice
# nx[] i ny[]
#---------------------
def setnn():
    # Dwa pierwsze punkty
    # to węzły początkowy
    # i końcowy
    nx.append(XS)
    nx.append(XE)

    # Pozostałe punkty
    # to węzły pośrednie
    for _ in range(2,NN+1):
        nx.append(XS + random() *
                 (XE - XS))

    # Porządkujemy rosnąco
    # współrzędne x węzłów
    nx.sort()

    # Teraz wyznaczamy
    # współrzędne y dla
    # uporządkowanych
    # współrzędnych x
    for s in nx:
        ny.append(f(s))

# Oblicza wartość interpolowaną
#------------------------------
def f_i(x0, y0, x1, y1, x):
    return (y0 + (y1 - y0) /
           (x1 - x0) * (x - x0))

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

# Przygotowujemy tablice
# nx[] i ny[]
setnn()

# Generujemy tablicę
# N współrzędnych x
# do interpolowania
# w przedziale <XS,XE>
x = [XS + random() * (XE - XS)
     for _ in range(N)]
y = []
for j in range(N):
    # Wyznaczamy segment, w którym
    # jest interpolowany punkt
    i = 0
    while i < NN and nx[i] < x[j]:
        i += 1

    i -= 1

    # interpolujemy
    y.append(f_i(nx[i],ny[i],
                 nx[i+1],ny[i+1],x[j]))

# Wyświetlamy wyniki:
print("Interpolacja liniowa\n"
      "--------------------\n")

for i in range(N):
    print(f"x = {x[i]:7.4f}"
          f", f(x) = {f(x[i]):7.4f}"
          f", interpolacja f(x) = "
          f"{y[i]: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.