|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
| SPIS TREŚCI REMANENT |
|
Równanie czwartego stopnia (ang. quartic equation) zbudowane jest z wielomianu czwartego stopnia:

Współczynniki a, b, c, d i e są liczbami rzeczywistymi.
Im wyższy stopień wielomianu, tym bardziej skomplikowane wzory opisują jego rozwiązania. Równanie stopnia czwartego jest ostatnim, które można rozwiązać algebraicznie. Udowodniono, że równania powyżej stopnia czwartego nie posiadają ogólnej metody rozwiązywania, co nie oznacza braku pierwiastków. Równania takie, oprócz przypadków szczególnych, rozwiązuje się przy pomocy metod przybliżonych.
Rozwiązania równań czwartego stopnia matematycy opracowali dopiero w XVI wieku. Powstało wiele metod rozwiązywania tych równań. Tutaj opiszemy tylko kilka najbardziej znanych.
Na początek zajmiemy się szczególnymi przypadkami równania czwartego stopnia, które stosunkowo łatwo rozwiązać (wykorzystując poznane wcześniej metody rozwiązywania równań wielomianowych).
Równanie dwukwadratowe (ang. biquadratic equation) ma postać:

Dokonujemy podstawienia:

Otrzymaliśmy równanie kwadratowe ze zmienną y. Rozwiązujemy je i otrzymujemy dwa pierwiastki: y1 i y2. Następnie otrzymujemy pierwiastki równania dwukwadratowego:

Jeśli któryś z pierwiastków y1 lub y2 jest ujemny lub zespolony, to otrzymamy w wyniku zespolone pierwiastki xi. Jeśli interesują nas tylko rozwiązania rzeczywiste, pomijamy rozwiązania zespolone. Możemy również wykonać rachunki na liczbach zespolonych i pomijać części urojone równe zero, otrzymując w ten sposób pierwiastki rzeczywiste (każda liczba rzeczywista ma część urojoną równą zero).
Załóżmy, że mamy liczbę zespoloną o postaci:

Pierwiastek zespolony tej liczby obliczymy ze wzoru:

Część rzeczywista pierwiastka zespolonego jest zawsze nieujemna. Znak części urojonej jest taki sam jak znak części urojonej pierwiastkowanej liczby (funkcja sgn(x) ma wartość -1 dla argumentów ujemnych, 0 dla argumentu 0 i 1 dla argumentu dodatniego).
Powyższy wzór pozwala nam rozwiązać dowolne równanie dwukwadratowe za pomocą metody rozwiązywania równań kwadratowych bez rozważania różnych przypadków.
Przykładowy program rozwiązuje dowolne równanie dwukwadratowe.
C++// Równanie czwartego stopnia
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0046
//---------------------------
#include <iostream>
#include <windows.h>
#include <cmath>
#include <iomanip>
using namespace std;
// Tutaj definiujemy
// dane wejściowe
//------------------
// Dokładność porównania
// z zerem
double epsy = 1e-12;
// Definicja typu zespolonego
struct cmplx
{
double re, im;
};
// Wyświetla + przed
// liczbą dodatnią,
// '-' przed ujemną
//------------------
void pl(double x)
{
if(x >= 0)
cout << '+';
else
cout << '-';
cout << fabs(x);
}
// Funkcja wylicza
// pierwiastek zespolony
//----------------------
void csqrt(cmplx y, cmplx & x)
{
double a,b;
a = y.re;
b = y.im;
double c = sqrt(a*a+b*b);
x.re = sqrt((c+a)/2.0);
x.im = sqrt((c-a)/2.0);
if(b < 0)
x.im = - x.im;
}
// Funkcja wyświetlająca
// liczbę zespoloną
//----------------------
void cmplxprint(cmplx x)
{
// Część rzeczywistą
// wyświetlamy zawsze
pl(x.re);
// Jeśli część urojona
// jest różna od zera,
// to ją wyświetlamy
if(fabs(x.im) > epsy)
{
pl(x.im);
cout << "i";
}
cout << endl;
}
// Funkcja rozwiązująca
// równanie dwukwadratowe
// a,b,c - współczynniki
// wielomianu
//-----------------------
void be(double a, double b, double c)
{
cout << "\nRównanie: ";
pl(a);
cout << "*x^4";
pl(b);
cout << "*x^2";
pl(c);
cout << " = 0\n";
double delta;
cmplx y1,y2,x1,x2,x3,x4;
// Zerujemy części
// urojone zmiennych
y1.im = 0.0;
y2.im = 0.0;
x1.im = 0.0;
x2.im = 0.0;
x3.im = 0.0;
x4.im = 0.0;
// Obliczamy wyróżnik
delta = b*b-4.0*a*c;
// Jeśli wyróżnik jest nieujemny,
// wyliczamy pierwiastki rzeczywiste
if(fabs(delta) < epsy)
{
y1.re = -b/2.0/a;
y2.re = y1.re;
}
else if(delta > 0)
{
delta = sqrt(delta);
y1.re = (-b-delta)/2.0/a;
y2.re = (-b+delta)/2.0/a;
}
else
{ // Inaczej wyliczamy
// pierwiastki zespolone
delta = sqrt(-delta);
y1.re = -b/2.0/a;
y2.re = y1.re;
y1.im = -delta/2.0/a;
y2.im = delta/2.0/a;
}
// Obliczamy pierwiastki
// zespolone rozwiązań
// równania kwadratowego
csqrt(y1,x1);
x1.re = -x1.re;
x1.im = -x1.im; // Ten jest ujemny
csqrt(y1,x2);
csqrt(y2,x3);
x3.re = -x3.re;
x3.im = -x3.im; // Ten jest ujemny
csqrt(y2,x4);
// Wyświetlamy wyniki:
cout << "x1 = "; cmplxprint(x1);
cout << "x2 = "; cmplxprint(x2);
cout << "x3 = "; cmplxprint(x3);
cout << "x4 = "; cmplxprint(x4);
}
// Program główny
//---------------
int main()
{
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout << setprecision(3)
<< fixed;
cout <<
"Równania dwukwadratowe typu\n"
" 4 2\n"
"ax + bx + c = 0\n"
"---------------------------\n";
be(1,-5,4);
be(1,-10,9);
be(4,7,-2);
be(3,2,5);
cout << endl;
system("pause");
return 0;
}
|
| Wynik |
Równania dwukwadratowe typu 4 2 ax + bx + c = 0 --------------------------- Równanie: +1.000*x^4-5.000*x^2+4.000 = 0 x1 = -1.000 x2 = +1.000 x3 = -2.000 x4 = +2.000 Równanie: +1.000*x^4-10.000*x^2+9.000 = 0 x1 = -1.000 x2 = +1.000 x3 = -3.000 x4 = +3.000 Równanie: +4.000*x^4+7.000*x^2-2.000 = 0 x1 = +0.000-1.414i x2 = +0.000+1.414i x3 = -0.500 x4 = +0.500 Równanie: +3.000*x^4+2.000*x^2+5.000 = 0 x1 = -0.692+0.901i x2 = +0.692-0.901i x3 = -0.692-0.901i x4 = +0.692+0.901i |
Python
(dodatek) # Równanie czwartego stopnia
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0046
# ---------------------------
from math import sqrt
# Tutaj definiujemy
# dane wejściowe
# ------------------
# Dokładność porównania
# z zerem
epsy = 1e-12
# Definicja typu zespolonego
class cmplx:
def __init__(self):
self.re = 0.0
self.im = 0.0
# Wyświetla + przed
# liczbą dodatnią,
# '-' przed ujemną
# ------------------
def pl(x):
if x >= 0:
print("+", end="")
else:
print("-", end="")
print(f"{abs(x):.3f}", end="")
# Funkcja wylicza
# pierwiastek zespolony
# ----------------------
def csqrt(y):
x = cmplx()
a = y.re
b = y.im
c = sqrt(a * a + b * b)
x.re = sqrt((c + a) / 2.0)
x.im = sqrt((c - a) / 2.0)
if b < 0:
x.im = -x.im
return x
# Funkcja wyświetlająca
# liczbę zespoloną
# ----------------------
def cmplxprint(x):
# Część rzeczywistą
# wyświetlamy zawsze
pl(x.re)
# Jeśli część urojona
# jest różna od zera,
# to ją wyświetlamy
if abs(x.im) > epsy:
pl(x.im)
print("i", end="")
print()
# Funkcja rozwiązująca
# równanie dwukwadratowe
# a,b,c - współczynniki
# wielomianu
# -----------------------
def be(a, b, c):
print("\nRównanie: ", end="")
pl(a)
print("*x^4", end="")
pl(b)
print("*x^2", end="")
pl(c)
print(" = 0")
y1 = cmplx()
y2 = cmplx()
# Obliczamy wyróżnik
delta = b * b - 4.0 * a * c
# Jeśli wyróżnik jest nieujemny,
# wyliczamy pierwiastki
# rzeczywiste
if abs(delta) < epsy:
y1.re = -b / 2.0 / a
y2.re = y1.re
y1.im = 0.0
y2.im = 0.0
elif delta > 0:
delta = sqrt(delta)
y1.re = (-b - delta) / 2 / a
y2.re = (-b + delta) / 2 / a
y1.im = 0.0
y2_im = 0.0
else:
# Inaczej wyliczamy
# pierwiastki zespolone
delta = sqrt(-delta)
y1.re = -b / 2.0 / a
y2.re = y1.re
y1.im = -delta / 2.0 / a
y2.im = delta / 2.0 / a
# Obliczamy pierwiastki
# zespolone rozwiązań
# równania kwadratowego
x1 = csqrt(y1)
x1.re = -x1.re
x1.im = -x1.im # Ten jest ujemny
x2 = csqrt(y1)
x3 = csqrt(y2)
x3.re = -x3.re
x3.im = -x3.im # Ten jest ujemny
x4 = csqrt(y2)
# Wyświetlamy wyniki:
print("x1 = ", end="")
cmplxprint(x1)
print("x2 = ", end="")
cmplxprint(x2)
print("x3 = ", end="")
cmplxprint(x3)
print("x4 = ", end="")
cmplxprint(x4)
# Program główny
# ---------------
print("Równania dwukwadratowe typu")
print(" 4 2")
print("ax + bx + c = 0")
print("---------------------------")
be(1, -5, 4)
be(1, -10, 9)
be(4, 7, -2)
be(3, 2, 5)
print()
input("Naciśnij Enter...")
|
Równanie czwartego stopnia o postaci:

możemy przekształcić do postaci:

Równanie to posiada pierwiastek równy zero. Pozostałe pierwiastki są pierwiastkami równania sześciennego i znajdujemy je metodami opisanymi w poprzednim rozdziale.
C++// Równanie czwartego stopnia
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0047
//---------------------------
#include <iostream>
#include <windows.h>
#define _USE_MATH_DEFINES
#include <cmath>
#include <iomanip>
using namespace std;
// Tutaj definiujemy
// dane wejściowe
//------------------
// Dokładność porównania
// z zerem
double epsy = 1e-12;
// Wyświetla + przed
// liczbą dodatnią,
// '-' przed ujemną
//------------------
void pl(double x)
{
if(x >= 0)
cout << '+';
else
cout << '-';
cout << fabs(x);
}
// Funkcja rozwiązująca
// równanie czwartego stopnia
// a,b,c,d - współczynniki
// --------------------------
void qe(double a, double b,
double c, double d)
{
double x1,x2,x3,p,q,delta;
// Znacznik wyniku
// zespolonego
bool cmplx = false;
cout << "\nRównanie: ";
pl(a);
cout << "*x^4";
pl(b);
cout << "*x^3";
pl(c);
cout << "*x^2";
pl(d);
cout << "*x = 0\n";
// Modyfikujemy współczynniki
// równania
d /= a;
c /= a;
b /= a;
a = b;
b = c;
c = d;
// Obliczamy wyróżnik delta
p = b-a*a/3.0;
q = 2.0*a*a*a/27.0-a*b/3.0+c;
delta = p*p*p/27.0+q*q/4.0;
// Sprawdzamy przypadki
if(fabs(delta) < epsy)
{
// 3 pierwiastki, 2 podwójne
q = ((q > 0)-(q < 0))*
pow(fabs(q)/2.0,1/3.0);
x1 = -2.0*q-a/3.0;
x2 = x3 = q-a/3.0;
}
else if(delta > 0)
{
// 1 pierwiastek rzeczywisty,
// 2 zespolone
cmplx = true; // Wynik zespolony
q /= -2.0;
delta = sqrt(delta);
x1 = ((q+delta > 0)-
(q+delta < 0))*
pow(fabs(q+delta),1/3.0)+
((q-delta > 0)-
(q-delta < 0))*
pow(fabs(q-delta),1/3.0)-a/3.0;
// Schematem Hornera dzielimy
// wielomian równania sześciennego
// przez dwumian (x - x1)
double aa,bb,cc;
aa = 1;
bb = a + aa * x1;
cc = b + bb * x1;
// Obliczamy wyróżnik
// równania kwadratowego
delta = bb*bb-4.0*aa*cc;
delta = sqrt(-delta);
// Część rzeczywista
x2 = - bb/2.0/aa;
// Część urojona
x3 = delta/2.0/aa;
}
else
{
// 3 pierwiastki rzeczywiste
a /= 3.0;
p = sqrt(-p);
double pp = 2.0/sqrt(3.0)*p;
q = 2.0*sqrt(3.0)*q/2.0/p/p/p;
x1 = pp*sin(asin(q)/3.0)-a;
x2 = -pp*sin(asin(q)/3.0+M_PI/3.0)-a;
x3 = pp*cos(asin(q)/3.0+M_PI/6.0)-a;
}
cout << "x1 = ";
pl(0.0);
cout << "\nx2 = ";
pl(x1);
cout << endl;
if(cmplx)
{
cout << "x3 = ";
pl(x2);
pl(-x3);
cout << "i\n"
"x4 = ";
pl(x2);
pl(x3);
cout << "i";
}
else
{
cout << "x3 = ";
pl(x2);
cout << "\nx4 = ";
pl(x3);
}
cout << endl;
}
// Program główny
//---------------
int main()
{
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout << setprecision(3)
<< fixed;
cout <<
"Równania czwartego stopnia typu\n"
" 4 3 2\n"
"ax + bx + cx + dx = 0\n"
"-------------------------------\n";
qe(1,3,3,1);
qe(1,-6,12,-8);
qe(1,9,27,27);
qe(1,-6,11,-6);
qe(1,-1,-16,-20);
qe(1,-2,-10,-25);
cout << endl;
system("pause");
return 0;
}
|
| Wyniki |
Równania czwartego stopnia typu 4 3 2 ax + bx + cx + dx = 0 ------------------------------- Równanie: +1.000*x^4+3.000*x^3+3.000*x^2+1.000*x = 0 x1 = +0.000 x2 = -1.000 x3 = -1.000 x4 = -1.000 Równanie: +1.000*x^4-6.000*x^3+12.000*x^2-8.000*x = 0 x1 = +0.000 x2 = +2.000 x3 = +2.000 x4 = +2.000 Równanie: +1.000*x^4+9.000*x^3+27.000*x^2+27.000*x = 0 x1 = +0.000 x2 = -3.000 x3 = -3.000 x4 = -3.000 Równanie: +1.000*x^4-6.000*x^3+11.000*x^2-6.000*x = 0 x1 = +0.000 x2 = +2.000 x3 = +1.000 x4 = +3.000 Równanie: +1.000*x^4-1.000*x^3-16.000*x^2-20.000*x = 0 x1 = +0.000 x2 = +5.000 x3 = -2.000 x4 = -2.000 Równanie: +1.000*x^4-2.000*x^3-10.000*x^2-25.000*x = 0 x1 = +0.000 x2 = +5.000 x3 = -1.500-1.658i x4 = -1.500+1.658i |
Python
(dodatek) # Równanie czwartego stopnia
# (C)2019 mgr Jerzy Wałaszek
# Metody numeryczne 0047
# ---------------------------
from math import sqrt,pow,asin,sin,cos,pi
# Tutaj definiujemy
# dane wejściowe
# ------------------
# Dokładność porównania z zerem
epsy = 1e-12
# Wyświetla + przed liczbą dodatnią,
# '-' przed ujemną
# ---------------------------------
def pl(x):
if x >= 0:
print("+", end="")
else:
print("-", end="")
print(f"{abs(x):.3f}", end="")
# Funkcja rozwiązująca
# równanie czwartego stopnia
# a,b,c,d - współczynniki
# --------------------------
def qe(a, b, c, d):
# Znacznik wyniku zespolonego
cmplx = False
print("\nRównanie: ", end="")
pl(a)
print("*x^4", end="")
pl(b)
print("*x^3", end="")
pl(c)
print("*x^2", end="")
pl(d)
print("*x = 0")
# Modyfikujemy współczynniki równania
d /= a
c /= a
b /= a
a = b
b = c
c = d
# Obliczamy wyróżnik delta
p = b-a*a/3
q = 2*a*a*a/27-a*b/3+c
delta = p*p*p/27+q*q/4
# Sprawdzamy przypadki
#---------------------
if abs(delta) < epsy:
# 3 pierwiastki, 2 podwójne
sgn = (q > 0)-(q < 0)
q = sgn*pow(abs(q)/2,1/3)
x1 = -2*q-a/3
x2 = q-a/3
x3 = x2
elif delta > 0:
# 1 pierwiastek rzeczywisty,
# 2 zespolone
cmplx = True # Wynik zespolony
q /= -2.0
delta = sqrt(delta)
v1 = q+delta
v2 = q-delta
sgn1 = (v1 > 0)-(v1 < 0)
sgn2 = (v2 > 0)-(v2 < 0)
x1 = (sgn1*pow(abs(v1),1/3)
+sgn2*pow(abs(v2),1/3)
-a/3)
# Schematem Hornera dzielimy
# wielomian równania
# sześciennego przez dwumian
# (x - x1)
aa = 1
bb = a+aa*x1
cc = b+bb*x1
# Obliczamy wyróżnik
# równania kwadratowego
delta = bb*bb-4*aa*cc
delta = sqrt(-delta)
# Część rzeczywista
x2 = -bb/2/aa
# Część urojona
x3 = delta/2/aa
else:
# 3 pierwiastki rzeczywiste
a /= 3
p = sqrt(-p)
pp = 2/sqrt(3)*p
q = 2*sqrt(3)*q/2/(p*p*p)
x1 = pp*sin(asin(q)/3)-a
x2 = (-pp*sin(asin(q)/3
+pi/3)-a)
x3 = ( pp*cos(asin(q)/3
+pi/6)-a)
print("x1 = ", end="")
pl(0.0)
print("\nx2 = ", end="")
pl(x1)
print()
if cmplx:
print("x3 = ", end="")
pl(x2)
pl(-x3)
print("i\nx4 = ", end="")
pl(x2)
pl(x3)
print("i", end="")
else:
print("x3 = ", end="")
pl(x2)
print("\nx4 = ", end="")
pl(x3)
print()
# Program główny
# ---------------
print("Równania czwartego stopnia typu")
print(" 4 3 2")
print("ax + bx + cx + dx = 0")
print("-------------------------------")
qe(1, 3, 3, 1)
qe(1, -6, 12, -8)
qe(1, 9, 27, 27)
qe(1, -6, 11, -6)
qe(1, -1, -16, -20)
qe(1, -2, -10, -25)
print()
input("Naciśnij Enter...")
|
Jeśli uda ci się znaleźć jeden pierwiastek x1 równania ax4+bx3+cx2+dx+e = 0, to wielomian tego równania możesz podzielić za pomocą schematu Hornera przez dwumian (x - x1):

W rezultacie otrzymasz równanie sześcienne, które rozwiązujesz metodami opisanymi w poprzednim rozdziale. Problem sprowadza się zatem do znalezienia pierwiastka rzeczywistego. Jeśli taki pierwiastek istnieje, to znajdziemy go jedną z metod przybliżonych, np. metodą Newtona. Przyjrzyjmy się wykresowi funkcji wielomianowej czwartego stopnia:

W zależności od znaku współczynnika a mamy dwa wykresy, tutaj w kolorze niebieskim i czerwonym. Pierwsza pochodna tej funkcji wyraża się wzorem:

Ponieważ pochodna jest wielomianem sześciennym, to zawsze istnieje takie x0, dla którego pochodna f'(x0) = 0. Wszystkie takie punkty są punktami krytycznymi funkcji wyjściowej. Jeśli pochodna w danym punkcie jest zerowa, to styczna w tym punkcie do wykresu funkcji jest równoległa do osi OX i metoda Newtona załamuje się. Zatem poszukując pierwiastka musimy tak dobrać punkt startowy, aby na drodze do pierwiastka pierwsza pochodna nie zerowała się. Musimy więc najpierw znaleźć wszystkie punkty krytyczne i dokonać odpowiednich wyborów. Punkty krytyczne znajdziemy rozwiązując równanie:

Równanie to rozwiązujemy metodą z poprzedniego rozdziału. Jako rozwiązania interesują nas tylko pierwiastki rzeczywiste, których może być jeden lub trzy. Rozważmy te przypadki:
Funkcja wyjściowa ma w tym przypadku jedno maksimum lub jedno minimum w punkcie xK.

Zwrot ramion wykresu zależy od znaku współczynnika a. Jeśli a jest dodatnie, to ramiona są skierowane do góry, a punkt K jest minimum funkcji (jak na obrazku powyżej). Jeśli a jest ujemne, to ramiona są skierowane w dół i punkt K jest maksimum funkcji:

Sprawdzamy teraz wartość f(xK):

W takim przypadku xK jest pierwiastkiem równania wyjściowego i możemy pominąć metodę Newtona, przyjmując x1 = xK.

Mamy maksimum/minimum w xK i dwa pierwiastki po obu stronach xK. Za punkt startowy wybieramy x0 = xK - 1 lub x0 = xK + 1 i szukamy pierwiastka metodą Newtona.
W pozostałych przypadkach funkcja f(x) nie ma pierwiastków rzeczywistych. Obliczenia przerywamy.
Funkcja wyjściowa f(x) posiada minima/maksima lokalne:


Porządkujemy punkty w kolejności:

Sprawdzamy, czy w którymś z tych punktów funkcja f(x) przyjmuje wartość 0. Jeśli tak, to mamy jeden pierwiastek x1 i pomijamy metodę Newtona.
Sprawdzamy, czy w dwóch sąsiednich punktach xK1 i xK2 lub xK2 i xK3 wartości funkcji mają różne znaki. Jeśli tak, to za punkt startowy x0 wybieramy średnią arytmetyczną tych punktów i uruchamiamy metodę Newtona, aby znaleźć pierwiastek x1.
Sprawdzamy przypadki:

Za punkt startowy wybieramy x0 = xK1 - 1 i uruchamiamy metodę Newtona.

Za punkt startowy wybieramy x0 = xK3 + 1 i uruchamiamy metodę Newtona.
W przeciwnym razie funkcja f(x) nie ma pierwiastków rzeczywistych i obliczenia przerywamy.
Gdy zostanie ustalony punkt startowy x0, wykorzystujemy metodę Newtona do znalezienia pierwiastka rzeczywistego x1 funkcji wyjściowej f(x).
Gdy znany jest pierwiastek x1, dzielimy wielomian funkcji wyjściowej f(x) przez dwumian (x - x1). Zadanie to wykonujemy przy pomocy schematu Hornera:

W rezultacie otrzymujemy wielomian sześcienny. Rozwiązujemy równanie a'x3+b'x2+c'x+d' = 0. Otrzymujemy pozostałe 3 pierwiastki x2, x3 i x4 i mamy pełne rozwiązanie równania czwartego stopnia.
Powyższa metoda pozwala znaleźć wszystkie pierwiastki równania czwartego stopnia, jeśli wśród nich występują pierwiastki rzeczywiste.
Metoda postępowania jest zatem następująca:
Jak widzisz, metoda ta łączy ze sobą kilka opisanych wcześniej metod. Rozwiązanie otrzymamy, jeśli równanie wyjściowe posiada pierwiastek rzeczywisty. W przypadku samych pierwiastków zespolonych algorytm zawodzi. Należy wtedy zastosować jedną z metod ogólnych, które opisujemy w dalszej części tego rozdziału.
Przykładowy program wykorzystujący opisaną tutaj metodę jest następujący:
C++// Równanie czwartego stopnia
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0048
//---------------------------
#include <iostream>
#include <windows.h>
#define _USE_MATH_DEFINES
#include <cmath>
#include <iomanip>
using namespace std;
// Tutaj definiujemy
// dane wejściowe
//------------------
// Dokładność porównania
// z zerem
double epsy = 1e-12;
// Wyświetla + przed
// liczbą dodatnią,
// '-' przed ujemną
//------------------
void pl(double x)
{
if(x >= 0)
cout << '+';
else
cout << '-';
cout << fabs(x);
}
// Funkcja oblicza wartość
// wielomianu metodą Hornera
//--------------------------
double f(double a, double b,
double c, double d,
double e, double x)
{
double w = a;
w = w * x + b;
w = w * x + c;
w = w * x + d;
w = w * x + e;
return w;
}
// Funkcja rozwiązująca
// równanie sześcienne
// a,b,c,d - współczynniki
// wielomianu
// cmplx - true, x1 = pierwiastek,
// x2 = re,
// x3 = +/- im
// - false,
// x1,x2,x3 =
// pierwiastki
// rzeczywiste
// x1,x2,x3 - pierwiastki
//--------------------------------
void ce(double a, double b,
double c, double d,
bool & cmplx,
double & x1,
double & x2,
double & x3)
{
double p,q,delta;
// Znacznik wyniku zespolonego
cmplx = false;
// Modyfikujemy współczynniki
// równania
d /= a;
c /= a;
b /= a;
a = b;
b = c;
c = d;
// Obliczamy wyróżnik delta
p = b-a*a/3.0;
q = 2.0*a*a*a/27.0-a*b/3.0+c;
delta = p*p*p/27.0+q*q/4.0;
// Sprawdzamy przypadki
if(fabs(delta) < epsy)
{ // 3 pierwiastki, 2 podwójne
q = ((q > 0) - (q < 0))*
pow(fabs(q)/2.0,1/3.0);
x1 = -2.0*q-a/3.0;
x2 = q-a/3.0;
x3 = x2;
}
else if(delta > 0)
{ // 1 pierwiastek rzeczywisty,
// 2 zespolone
// Wynik zespolony
cmplx = true;
q /= -2.0;
delta = sqrt(delta);
x1 = ((q+delta > 0)-(q+delta < 0))*
pow(fabs(q+delta),1/3.0)+
((q-delta > 0)-(q-delta < 0))*
pow(fabs(q-delta),1/3.0)-a/3.0;
// Schematem Hornera dzielimy
// wielomian równania sześciennego
// przez dwumian (x - x1)
double aa,bb,cc;
aa = 1;
bb = a+aa*x1;
cc = b+bb*x1;
// Obliczamy wyróżnik
// równania kwadratowego
delta = bb*bb-4*aa*cc;
delta = sqrt(-delta);
// Część rzeczywista
x2 = -bb/2.0/aa;
// Część urojona
x3 = delta/2.0/aa;
}
else // 3 pierwiastki rzeczywiste
{
a /= 3.0;
p = sqrt(-p);
double pp = 2.0/sqrt(3.0)* p;
q = 3.0*sqrt(3.0)*q/2.0/p/p/p;
x1 = pp*sin(asin(q)/3.0)-a;
x2 = -pp*sin(asin(q)/3.0+M_PI/3.0)-a;
x3 = pp*cos(asin(q)/3.0+M_PI/6.0)-a;
}
}
// Funkcja rozwiązująca równanie
// czwartego stopnia
// a,b,c,d,e - współczynniki
// wielomianu
//------------------------------
void qe(double a, double b,
double c, double d,
double e)
{
double x0,x1,x2,x3,x4;
bool cmplx,noresult,newton;
cout << "\nRównanie: ";
pl(a);
cout << "*x^4";
pl(b);
cout << "*x^3";
pl(c);
cout << "*x^2";
pl(d);
cout << "*x";
pl(e);
cout << " = 0\n";
// Wyznaczamy pierwiastki pochodnej
ce(4.0*a,3.0*b,2.0*c,
d,cmplx,x1,x2,x3);
// Znacznik braku pierwiastków
noresult = false;
// Znacznik obliczania pierwiastka
// metodą Newtona
newton = true;
if(cmplx)
{ // Jeden pierwiastek rzeczywisty
// Obliczamy wartość w punkcie xk
double yk = f(a,b,c,d,e,x1);
if(fabs(yk) < epsy)
// Mamy jeden pierwiastek
newton = false;
else if(yk * a < 0)
// Punkt startowy
// dla metody Newtona
x0 = x1 - 1;
else
// Brak pierwiastków
// rzeczywistych
noresult = true;
}
else
{ // Trzy pierwiastki rzeczywiste
// Porządkujemy punkty krytyczne
if(x1 > x2) swap(x1,x2);
if(x2 > x3) swap(x2,x3);
if(x1 > x2) swap(x1,x2);
double yk1,yk2,yk3;
// Obliczamy wartości wielomianu
// w punktach krytycznych
yk1 = f(a,b,c,d,e,x1);
yk2 = f(a,b,c,d,e,x2);
yk3 = f(a,b,c,d,e,x3);
// Sprawdzamy, czy w którymś
// z punktów krytycznych
// wielomian zeruje się
if(fabs(yk1) < epsy)
newton = false;
else if(fabs(yk2) < epsy)
{
newton = false;
x1 = x2;
}
else if(fabs(yk3) < epsy)
{
newton = false;
x1 = x3;
}
// Punkty startowe
// dla metody Newtona
else if(yk1 * yk2 < 0)
x0 = (x1 + x2) / 2.0;
else if(yk2 * yk3 < 0)
x0 = (x2 + x3) / 2.0;
else if(yk1 * a < 0)
x0 = x1 - 1;
else if(yk3 * a < 0)
x0 = x3 + 1;
else noresult = true;
}
// Jeśli brak pierwiastków,
// przerywamy obliczenia
if(noresult)
{
cout <<
"BRAK PIERWIASTKÓW RZECZYWISTYCH\n"
"Obliczenia zostały przerwane!!!\n\n";
return;
}
// Jeśli nie znaleziono pierwiastka,
// uruchamiamy metodę Newtona
if(newton)
{
// Dokładność wyznaczania zera
double epsx = 1e-14;
// Maksymalna liczba obiegów
int n = 64;
double f0,f1;
bool result = false;
while(--n)
{
// Obliczamy wartość
// funkcji w punkcie x0
f0 = f(a,b,c,d,e,x0);
// Sprawdzamy, czy funkcja
// jest dostatecznie
// bliska zeru
if(fabs(f0) < epsy)
{
result = true;
break;
}
// Obliczamy wartość
// pierwszej pochodnej funkcji
f1 = f(0,4.0*a,3.0*b,2.0*c,d,x0);
// Zapamiętujemy bieżące
// przybliżenie
x1 = x0;
// Obliczamy kolejne przybliżenie
x0 -= f0/f1;
// Sprawdzamy, czy odległość
// pomiędzy dwoma ostatnimi
// przybliżeniami jest mniejsza
// od założonej dokładności
if(fabs(x1 - x0) < epsx)
{
result = true;
break;
}
// Kontynuujemy obliczenia
}
if(!result)
{
cout <<
"BŁĄD W METODZIE NEWTONA\n"
"Obliczenia przerwane!!!\n\n";
return;
}
// Pierwszy pierwiastek
// z metody Newtona
x1 = x0;
}
// W x1 mamy pierwiastek rzeczywisty
// Schematem Hornera dzielimy
// wielomian równania przez
// dwumian (x - x1)
double aa,bb,cc,dd;
aa = a;
bb = b + aa * x1;
cc = c + bb * x1;
dd = d + cc * x1;
// Obliczamy pierwiastki
// wynikowego równania
// sześciennego
ce(aa,bb,cc,dd,cmplx,x2,x3,x4);
// Wyświetlamy wyniki
cout << "x1 = ";
pl(x1);
cout << "\nx2 = ";
pl(x2);
cout << endl;
if(cmplx)
{
cout << "x3 = ";
pl(x3);
pl(-x4);
cout << "i\n"
"x4 = ";
pl(x3);
pl(x4);
cout << "i";
}
else
{
cout << "x3 = ";
pl(x3);
cout << "\nx4 = ";
pl(x4);
}
cout << endl;
}
// Program główny
//---------------
int main()
{
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout << setprecision(3)
<< fixed;
cout <<
"Równania czwartego stopnia typu\n"
" 4 3 2\n"
"ax + bx + cx + dx + e = 0\n"
"-------------------------------\n";
qe(1,-10,35,-50,24);
qe(1,-4,3,4,-4);
qe(1,1,-7,-1,6);
cout << endl;
system("pause");
return 0;
}
|
| Wynik |
Równania czwartego stopnia typu 4 3 2 ax + bx + cx + dx + e = 0 ------------------------------- Równanie: +1.000*x^4-10.000*x^3+35.000*x^2-50.000*x+24.000 = 0 x1 = +2.000 x2 = +3.000 x3 = +1.000 x4 = +4.000 Równanie: +1.000*x^4-4.000*x^3+3.000*x^2+4.000*x-4.000 = 0 x1 = +2.000 x2 = +1.000 x3 = -1.000 x4 = +2.000 Równanie: +1.000*x^4+1.000*x^3-7.000*x^2-1.000*x+6.000 = 0 x1 = -1.000 x2 = +1.000 x3 = -3.000 x4 = +2.000 |
Python
(dodatek) # Równanie czwartego stopnia
# (C)2019 mgr Jerzy Wałaszek
# Metody numeryczne 0048
# ---------------------------
from math import asin,cos,pi,pow,sin,sqrt
# Tutaj definiujemy dane wejściowe
# --------------------------------
# Dokładność porównania z zerem
epsy = 1e-12
# Wyświetla + przed
# liczbą dodatnią,
# '-' przed ujemną
# ------------------
def pl(x):
if x >= 0:
print("+", end="")
else:
print("-", end="")
print(f"{abs(x):.3f}", end="")
# Funkcja oblicza wartość
# wielomianu metodą Hornera
# --------------------------
def f(a, b, c, d, e, x):
w = a
w = w * x + b
w = w * x + c
w = w * x + d
w = w * x + e
return w
# Funkcja rozwiązująca
# równanie sześcienne
# a,b,c,d - współczynniki
# wielomianu
# cmplx - true, x1 = pierwiastek,
# x2 = re,
# x3 = +/- im
# - false,
# x1,x2,x3 =
# pierwiastki
# rzeczywiste
# x1,x2,x3 - pierwiastki
# --------------------------------
def ce(a, b, c, d):
# Znacznik wyniku zespolonego
cmplx = False
# Modyfikujemy współczynniki
# równania
d /= a
c /= a
b /= a
a = b
b = c
c = d
# Obliczamy wyróżnik delta
p = b-a*a/3
q = 2.0*a*a*a/27-a*b/3+c
delta = p*p*p/27+q*q/4
# Sprawdzamy przypadki
if abs(delta) < epsy:
# 3 pierwiastki, 2 podwójne
sgn = (q > 0)-(q < 0)
q = sgn*pow(abs(q)/2,1/3)
x1 = -2.0*q-a/3
x2 = q-a/3
x3 = x2
elif delta > 0:
# 1 pierwiastek rzeczywisty,
# 2 zespolone
# Wynik zespolony
cmplx = True
q /= -2
delta = sqrt(delta)
v1 = q+delta
v2 = q-delta
sgn1 = (v1 > 0)-(v1 < 0)
sgn2 = (v2 > 0)-(v2 < 0)
x1 = (sgn1*pow(abs(v1),1/3)
+sgn2*pow(abs(v2),1/3)
-a/3)
# Schematem Hornera dzielimy
# wielomian równania
# sześciennego przez dwumian
# (x - x1)
aa = 1
bb = a + aa * x1
cc = b + bb * x1
# Obliczamy wyróżnik
# równania kwadratowego
delta = bb*bb-4*aa*cc
delta = sqrt(-delta)
# Część rzeczywista
x2 = -bb/2/aa
# Część urojona
x3 = delta/2/aa
else:
# 3 pierwiastki rzeczywiste
a /= 3
p = sqrt(-p)
pp = 2/sqrt(3)*p
q = 3*sqrt(3)*q/2/(p*p*p)
x1 = pp*sin(asin(q)/3)-a
x2 = (-pp*sin(asin(q)/3+pi/3)-a)
x3 = ( pp*cos(asin(q)/3+pi/6)-a)
return cmplx, x1, x2, x3
# Funkcja rozwiązująca równanie
# czwartego stopnia
# a,b,c,d,e - współczynniki
# wielomianu
# ------------------------------
def qe(a, b, c, d, e):
print("\nRównanie: ", end="")
pl(a)
print("*x^4", end="")
pl(b)
print("*x^3", end="")
pl(c)
print("*x^2", end="")
pl(d)
print("*x", end="")
pl(e)
print(" = 0")
# Wyznaczamy pierwiastki pochodnej
cmplx,x1,x2,x3 = ce(4*a,3*b,2*c,d)
# Znacznik braku pierwiastków
noresult = False
# Znacznik obliczania pierwiastka
# metodą Newtona
newton = True
if cmplx:
# Jeden pierwiastek rzeczywisty
# Obliczamy wartość w punkcie xk
yk = f(a, b, c, d, e, x1)
if abs(yk) < epsy:
# Mamy jeden pierwiastek
newton = False
elif yk * a < 0:
# Punkt startowy
# dla metody Newtona
x0 = x1 - 1
else:
# Brak pierwiastków
# rzeczywistych
noresult = True
else:
# Trzy pierwiastki rzeczywiste
# Porządkujemy punkty krytyczne
if x1 > x2:
x1, x2 = x2, x1
if x2 > x3:
x2, x3 = x3, x2
if x1 > x2:
x1, x2 = x2, x1
# Obliczamy wartości wielomianu
# w punktach krytycznych
yk1 = f(a, b, c, d, e, x1)
yk2 = f(a, b, c, d, e, x2)
yk3 = f(a, b, c, d, e, x3)
# Sprawdzamy, czy w którymś
# z punktów krytycznych
# wielomian zeruje się
if abs(yk1) < epsy:
newton = False
elif abs(yk2) < epsy:
newton = False
x1 = x2
elif abs(yk3) < epsy:
newton = False
x1 = x3
# Punkty startowe
# dla metody Newtona
elif yk1 * yk2 < 0:
x0 = (x1+x2)/2
elif yk2 * yk3 < 0:
x0 = (x2+x3)/2
elif yk1 * a < 0:
x0 = x1-1
elif yk3 * a < 0:
x0 = x3+1
else:
noresult = True
# Jeśli brak pierwiastków,
# przerywamy obliczenia
if noresult:
print(
"BRAK PIERWIASTKÓW RZECZYWISTYCH\n"
"Obliczenia zostały przerwane!!!\n")
return
# Jeśli nie znaleziono pierwiastka,
# uruchamiamy metodę Newtona
if newton:
# Dokładność wyznaczania zera
epsx = 1e-14
# Maksymalna liczba obiegów
n = 64
bool_res = False
while n > 0:
n -= 1
# Obliczamy wartość
# funkcji w punkcie x0
f0 = f(a, b, c, d, e, x0)
# Sprawdzamy, czy funkcja
# jest dostatecznie
# bliska zeru
if abs(f0) < epsy:
bool_res = True
break
# Obliczamy wartość
# pierwszej pochodnej funkcji
f1 = f(0,4*a,3*b,2*c,d,x0)
# Zapamiętujemy bieżące
# przybliżenie
x1 = x0
# Obliczamy kolejne
# przybliżenie
x0 -= f0/f1
# Sprawdzamy, czy odległość
# pomiędzy dwoma ostatnimi
# przybliżeniami jest mniejsza
# od założonej dokładności
if abs(x1 - x0) < epsx:
bool_res = True
break
# Kontynuujemy obliczenia
if not bool_res:
print(
"BŁĄD W METODZIE NEWTONA\n"
"Obliczenia przerwane!!!\n")
return
# Pierwszy pierwiastek
# z metody Newtona
x1 = x0
# W x1 mamy pierwiastek rzeczywisty
# Schematem Hornera dzielimy
# wielomian równania przez
# dwumian (x - x1)
aa = a
bb = b + aa * x1
cc = c + bb * x1
dd = d + cc * x1
# Obliczamy pierwiastki
# wynikowego równania
# sześciennego
cmplx,x2,x3,x4 = ce(aa,bb,cc,dd)
# Wyświetlamy wyniki
print("x1 = ", end="")
pl(x1)
print("\nx2 = ", end="")
pl(x2)
print()
if cmplx:
print("x3 = ", end="")
pl(x3)
pl(-x4)
print("i\nx4 = ", end="")
pl(x3)
pl(x4)
print("i", end="")
else:
print("x3 = ", end="")
pl(x3)
print("\nx4 = ", end="")
pl(x4)
print()
# Program główny
# ---------------
print("Równania czwartego stopnia typu\n"
" 4 3 2\n"
"ax + bx + cx + dx + e = 0\n"
"-------------------------------")
qe(1, -10, 35, -50, 24)
qe(1, -4, 3, 4, -4)
qe(1, 1, -7, -1, 6)
print()
input("Naciśnij Enter...")
|
Równanie czwartego stopnia można również rozwiązać algebraicznie za pomocą jednej z kilku metod. Tutaj przedstawimy metodę, która wykorzystuje pośrednie równanie sześcienne. Metoda pochodzi od włoskiego matematyka Lodovico Ferrari. Najpierw zobaczmy, jaką naturę mogą mieć pierwiastki równania czwartego stopnia:
Mamy ogólne równanie czwartego stopnia:

Załóżmy, że równanie to posiada pierwiastek rzeczywisty x1. W takim przypadku wielomian równania czwartego stopnia możemy zawsze podzielić przez dwumian (x - x1):

Pozostałe 3 pierwiastki są pierwiastkami równania:

Ponieważ jest to równanie sześcienne, to pozostałe 3 pierwiastki mogą być albo wszystkie rzeczywiste, albo jeden rzeczywisty i dwa zespolone. Wynika z tego, iż równanie czwartego stopnia może mieć:
Metoda rozwiązywania równania czwartego stopnia jest następująca:
Mamy ogólne równanie czwartego stopnia:

Wyliczamy 3 kolejne współczynniki wg wzorów:

Z wyliczonych współczynników tworzymy pomocnicze równanie sześcienne:

Równanie to rozwiązujemy za pomocą metod opisanych w poprzednim rozdziale. Otrzymujemy trzy pierwiastki y1, y2 i y3. Wybieramy z nich dwa pierwiastki, które są różne od zera (jeśli mamy jeden pierwiastek rzeczywisty i dwa zespolone, zawsze wybieramy pierwiastki zespolone, które są liczbami sprzężonymi) i wyliczamy ich pierwiastki (mogą być zespolone):

Dodatkowo wyliczamy:

Pierwiastki równania wyjściowego otrzymujemy ze wzorów:

W działaniach mogą pojawiać się liczby zespolone, dlatego rachunki najlepiej przeprowadzać na liczbach zespolonych, dzięki czemu unikniemy rozważania różnych przypadków. Podobnie postąpiliśmy w algorytmie nr 1. Zasady działań na liczbach zespolonych są następujące (więcej na temat liczb zespolonych znajdziesz tutaj):


Poniższy program jest przykładową realizacją tego algorytmu:
C++// Równanie czwartego stopnia
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0049
//---------------------------
#include <iostream>
#include <windows.h>
#define _USE_MATH_DEFINES
#include <cmath>
#include <iomanip>
using namespace std;
// Tutaj definiujemy
// dane wejściowe
//------------------
// Dokładność porównania
// z zerem
double epsy = 1e-12;
// Liczby zespolone
//-----------------
// Definicja typu zespolonego
struct cmplx
{
double re, im;
};
// Mnożenie liczb zespolonych
// c = a * b
//----------------------------
void cmplx_mul(cmplx a,
cmplx b,
cmplx & c)
{
c.re = a.re*b.re-a.im*b.im;
c.im = a.re*b.im+a.im*b.re;
}
// Dzielenie liczb zespolonych
// c = a / b
//----------------------------
void cmplx_div(cmplx a,
cmplx b,
cmplx & c)
{
double d = b.re*b.re+b.im*b.im;
c.re = (a.re*b.re+a.im*b.im)/d;
c.im = (a.im*b.re-a.re*b.im)/d;
}
// Pierwiastkowanie liczb zespolonych
// b = sqrt(a)
//-----------------------------------
void cmplx_sqrt(cmplx a,
cmplx & b)
{
double x,y;
x = a.re;
y = a.im;
double c = sqrt(x*x+y*y);
b.re = sqrt((c+x)/2.0);
b.im = sqrt((c-x)/2.0);
if(a.im < 0)
b.im = -b.im;
}
// Wyświetla + przed
// liczbą dodatnią,
// '-' przed ujemną
//------------------
void pl(double x)
{
if(x >= 0)
cout << '+';
else
cout << '-';
cout << fabs(x);
}
// Wyświetlanie liczby
// zespolonej
void cmplx_print(cmplx a)
{
pl(a.re);
if(fabs(a.im) >= epsy)
{
pl(a.im);
cout << "i";
}
cout << endl;
}
// Funkcja rozwiązująca
// równanie sześcienne
// a,b,c,d - współczynniki
// wielomianu
// cmplx - true, x1 = pierwiastek,
// x2 = re,
// x3 = +/- im
// false, x1,x2,x3 = pierwiastki
// rzeczywiste
// x1,x2,x3 - pierwiastki
//-------------------------------------
void ce(double a, double b,
double c, double d,
bool & cmpl,
double & x1,
double & x2,
double & x3)
{
double p,q,delta;
// Znacznik wyniku
// zespolonego
cmpl = false;
// Modyfikujemy współczynniki
// równania
d /= a;
c /= a;
b /= a;
a = b;
b = c;
c = d;
// Obliczamy wyróżnik delta
p = b-a*a/3.0;
q = 2.0*a*a*a/27.0-a*b/3.0+c;
delta = p*p*p/27.0+q*q/4.0;
// Sprawdzamy przypadki
if(fabs(delta) < epsy)
{
// 3 pierwiastki, 2 podwójne
q = ((q > 0)-(q < 0))*
pow(fabs(q)/2.0,1/3.0);
x1 = -2*q-a/3.0;
x2 = x3 = q-a/3.0;
}
else if(delta > 0)
{
// 1 pierwiastek rzeczywisty,
// 2 zespolone
cmpl = true; // Wynik zespolony
q /= -2.0;
delta = sqrt(delta);
x1 = ((q+delta > 0)-
(q+delta < 0))*
pow(fabs(q+delta),1/3.0)+
((q-delta > 0)-(q-delta < 0))*
pow(fabs(q-delta),1/3.0)-a/3.0;
// Schematem Hornera dzielimy
// wielomian równania sześciennego
// przez dwumian (x - x1)
double aa,bb,cc;
aa = 1;
bb = a+aa*x1;
cc = b+bb*x1;
// Obliczamy wyróżnik
// równania kwadratowego
delta = bb*bb-4.0*aa*cc;
delta = sqrt(-delta);
// Część rzeczywista
x2 = -bb/2.0/aa;
// Część urojona
x3 = delta/2/aa;
}
else
{
// 3 pierwiastki rzeczywiste
a /= 3.0;
p = sqrt(-p);
double pp = 2.0/sqrt(3.0)*p;
q = 3.0*sqrt(3.0)*q/2.0/p/p/p;
x1 = pp*sin(asin(q)/3.0)-a;
x2 = -pp*sin(asin(q)/3.0+M_PI/3.0)-a;
x3 = pp*cos(asin(q)/3.0+M_PI/6)-a;
}
}
// Funkcja rozwiązująca
// równanie czwartego stopnia
// a,b,c,d,e - współczynniki
// wielomianu
//---------------------------
void qe(double a, double b,
double c, double d,
double e)
{
cout << "\nRównanie: ";
pl(a);
cout << "*x^4";
pl(b);
cout << "*x^3";
pl(c);
cout << "*x^2";
pl(d);
cout << "*x";
pl(e);
cout << " = 0\n";
double f,g,h;
// Wyliczamy współczynniki
f = (c-3.0*b*b/8.0/a)/a;
g = (d+b*b*b/8.0/a/a-b*c/2.0/a)/a;
h = (e-3.0*b*b*b*b/256.0/a/a/a+
b*b*c/16.0/a/a-
b*d/4.0/a)/a;
double x1,x2,x3;
bool cmpl;
// Tworzymy pomocnicze równanie
// sześcienne i wyliczamy jego
// pierwiastki
ce(1,f/2.0,(f*f-4.0*h)/16.0,
-g*g/64.0,cmpl,x1,x2,x3);
cmplx y1, y2;
// Pierwiastki zespolone
if(cmpl)
{
y1.re = y2.re = x2;
y1.im = -x3;
y2.im = x3;
}
else
{
// Wybieramy dwa niezerowe
// pierwiastki
y1.im = y2.im = 0;
if(fabs(x1) < epsy)
{
y1.re = x2;
y2.re = x3;
}
else if(fabs(x2) < epsy)
{
y1.re = x1;
y2.re = x3;
}
else
{
y1.re = x1;
y2.re = x2;
}
}
// Obliczamy ich
// pierwiastki zespolone
cmplx p,q,r,t,u;
double s;
cmplx_sqrt(y1,p);
cmplx_sqrt(y2,q);
// Wyliczamy współczynniki s i r
s = b/4.0/a;
cmplx_mul(p,q,t);
u.re = -g/8.0;
u.im = 0;
cmplx_div(u,t,r);
// Obliczamy pierwiastki
// zespolone równania
// czwartego stopnia
cmplx r1,r2,r3,r4;
r1.re = p.re+q.re+r.re-s;
r1.im = p.im+q.im+r.im;
r2.re = p.re-q.re-r.re-s;
r2.im = p.im-q.im-r.im;
r3.re = -p.re+q.re-r.re-s;
r3.im = -p.im+q.im-r.im;
r4.re = -p.re-q.re+r.re-s;
r4.im = -p.im-q.im+r.im;
// Wyświetlamy wyniki
cout << "x1 = "; cmplx_print(r1);
cout << "x2 = "; cmplx_print(r2);
cout << "x3 = "; cmplx_print(r3);
cout << "x4 = "; cmplx_print(r4);
}
// Program główny
//---------------
int main()
{
cout << setprecision(3)
<< fixed;
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout <<
"Równania czwartego stopnia typu\n"
" 4 3 2\n"
"ax + bx + cx + dx + e = 0\n"
"-------------------------------\n";
qe(1,-10,35,-50,24);
qe(1,-4,3,4,-4);
qe(1,1,-7,-1,6);
qe(5,5,5,5,5);
cout << endl;
system("pause");
return 0;
}
|
| Wynik |
Równania czwartego stopnia typu 4 3 2 ax + bx + cx + dx + e = 0 ------------------------------- Równanie: +1.000*x^4-10.000*x^3+35.000*x^2-50.000*x+24.000 = 0 x1 = +4.000 x2 = +2.000 x3 = +3.000 x4 = +1.000 Równanie: +1.000*x^4-4.000*x^3+3.000*x^2+4.000*x-4.000 = 0 x1 = +2.000 x2 = +2.000 x3 = +1.000 x4 = -1.000 Równanie: +1.000*x^4+1.000*x^3-7.000*x^2-1.000*x+6.000 = 0 x1 = -1.000 x2 = +2.000 x3 = +1.000 x4 = -3.000 Równanie: +5.000*x^4+5.000*x^3+5.000*x^2+5.000*x+5.000 = 0 x1 = +0.309+0.951i x2 = -0.809-0.588i x3 = -0.809+0.588i x4 = +0.309-0.951i |
Python
(dodatek) # Równanie czwartego stopnia
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0049
# --------------------------
from math import asin,cos,pi,pow,sin,sqrt
# Tutaj definiujemy
# dane wejściowe
# -----------------
# Dokładność porównania
# z zerem
epsy = 1e-12
# Liczby zespolone
# ----------------
# Definicja typu zespolonego
class cmplx:
def __init__(self):
self.re = 0.0
self.im = 0.0
# Mnożenie liczb zespolonych
# c = a * b
#---------------------------
def cmplx_mul(a, b):
c = cmplx()
c.re = a.re*b.re-a.im*b.im
c.im = a.re*b.im+a.im*b.re
return c
# Dzielenie liczb zespolonych
# c = a / b
#----------------------------
def cmplx_div(a, b):
c = cmplx()
d = b.re*b.re+b.im*b.im
c.re = (a.re*b.re+a.im*b.im)/d
c.im = (a.im*b.re-a.re*b.im)/d
return c
# Pierwiastkowanie liczb zespolonych
# b = sqrt(a)
#-----------------------------------
def cmplx_sqrt(a):
b = cmplx()
x = a.re
y = a.im
c = sqrt(x*x+y*y)
b.re = sqrt((c+x)/2)
b.im = sqrt((c-x)/2)
if a.im < 0:
b.im = -b.im
return b
# Wyświetla + przed
# liczbą dodatnią,
# '-' przed ujemną
# ------------------
def pl(x):
if x >= 0:
print("+", end="")
else:
print("-", end="")
print(f"{abs(x):.3f}", end="")
# Wyświetlanie liczby
# zespolonej
def cmplx_print(a):
pl(a.re)
if abs(a.im) >= epsy:
pl(a.im)
print("i", end="")
print()
# Funkcja rozwiązująca
# równanie sześcienne
# a,b,c,d - współczynniki
# wielomianu
# cmplx - true, x1 = pierwiastek,
# x2 = re,
# x3 = +/- im
# - false, x1,x2,x3 = pierwiastki
# rzeczywiste
# x1,x2,x3 - pierwiastki
# ------------------------------------
def ce(a, b, c, d):
# Znacznik wyniku
# zespolonego
cmpl = False
# Modyfikujemy współczynniki
# równania
d /= a
c /= a
b /= a
a = b
b = c
c = d
# Obliczamy wyróżnik delta
p = b-a*a/3
q = 2*a*a*a/27-a*b/3+ c
delta = p*p*p/27+q*q/4
# Sprawdzamy przypadki
if abs(delta) < epsy:
# 3 pierwiastki, 2 podwójne
sgn = (q > 0) - (q < 0)
q = sgn*pow(abs(q)/2,1/3)
x1 = -2*q-a/3
x2 = q-a/3
x3 = x2
elif delta > 0:
# 1 pierwiastek rzeczywisty,
# 2 zespolone
cmpl = True # Wynik zespolony
q /= -2
delta = sqrt(delta)
v1 = q + delta
v2 = q - delta
sgn1 = (v1 > 0) - (v1 < 0)
sgn2 = (v2 > 0) - (v2 < 0)
x1 = (sgn1*pow(abs(v1),1/3)
+sgn2*pow(abs(v2),1/3)
-a/3)
# Schematem Hornera dzielimy
# wielomian równania
# sześciennego przez dwumian
# (x - x1)
aa = 1
bb = a+aa*x1
cc = b+bb*x1
# Obliczamy wyróżnik
# równania kwadratowego
delta = bb*bb-4*aa* cc
delta = sqrt(-delta)
# Część rzeczywista
x2 = -bb/2/aa
# Część urojona
x3 = delta/2/aa
else:
# 3 pierwiastki rzeczywiste
a /= 3
p = sqrt(-p)
pp = 2/sqrt(3)*p
q = 3*sqrt(3)*q/2/(p*p*p)
x1 = pp*sin(asin(q)/3)-a
x2 = -pp*sin(asin(q)/3+pi/3)-a
x3 = pp*cos(asin(q)/3+pi/6)-a
return cmpl, x1, x2, x3
# Funkcja rozwiązująca
# równanie czwartego stopnia
# a,b,c,d,e - współczynniki
# wielomianu
# --------------------------
def qe(a, b, c, d, e):
print("\nRównanie: ", end="")
pl(a)
print("*x^4", end="")
pl(b)
print("*x^3", end="")
pl(c)
print("*x^2", end="")
pl(d)
print("*x", end="")
pl(e)
print(" = 0")
# Wyliczamy współczynniki
f = (c-3*b*b/8/a)/a
g = (d+b*b*b/8/a/a-b*c/2/a)/a
h = (e-3*b*b*b*b/256/a/a/a
+b*b*c/16/a/a-b*d/4/a)/a
# Tworzymy pomocnicze równanie
# sześcienne i wyliczamy jego
# pierwiastki
cmpl,x1,x2,x3 = ce(1,f/2,
(f*f-4*h)/16,
-g*g/64)
y1 = cmplx()
y2 = cmplx()
# Pierwiastki zespolone
if cmpl:
y1.re = y2.re = x2
y1.im = -x3
y2.im = x3
else:
# Wybieramy dwa niezerowe
# pierwiastki
y1.im = y2.im = 0
if abs(x1) < epsy:
y1.re = x2
y2.re = x3
elif abs(x2) < epsy:
y1.re = x1
y2.re = x3
else:
y1.re = x1
y2.re = x2
# Obliczamy ich
# pierwiastki zespolone
u = cmplx()
p = cmplx_sqrt(y1)
q = cmplx_sqrt(y2)
# Wyliczamy współczynniki s i r
s = b/4/a
t = cmplx_mul(p, q)
u.re = -g/8.0
u.im = 0
r = cmplx_div(u, t)
# Obliczamy pierwiastki
# zespolone równania
# czwartego stopnia
r1 = cmplx()
r2 = cmplx()
r3 = cmplx()
r4 = cmplx()
r1.re = p.re+q.re+r.re-s
r1.im = p.im+q.im+r.im
r2.re = p.re-q.re-r.re-s
r2.im = p.im-q.im-r.im
r3.re = -p.re+q.re-r.re-s
r3.im = -p.im+q.im-r.im
r4.re = -p.re-q.re+r.re-s
r4.im = -p.im-q.im+r.im
# Wyświetlamy wyniki
print("x1 = ", end="")
cmplx_print(r1)
print("x2 = ", end="")
cmplx_print(r2)
print("x3 = ", end="")
cmplx_print(r3)
print("x4 = ", end="")
cmplx_print(r4)
# Program główny
# ---------------
print("Równania czwartego stopnia typu")
print(" 4 3 2")
print("ax + bx + cx + dx + e = 0")
print("-------------------------------")
qe(1, -10, 35, -50, 24)
qe(1, -4, 3, 4, -4)
qe(1, 1, -7, -1, 6)
qe(5, 5, 5, 5, 5)
print()
input("Naciśnij Enter...")
|
Równanie stopnia czwartego jest ostatnim równaniem wielomianowym, dla którego istnieje algebraiczna metoda rozwiązywania. Udowodniono, że nie ma takiej metody dla równań o stopniu wyższym niż 4. Nie oznacza to oczywiście, że równania takie nie posiadają pierwiastków. Nie można jedynie znaleźć tych pierwiastków ogólną metodą o skończonej liczbie operacji. Pozostają nam zatem metody przybliżone lub metody rozwiązujące szczególne przypadki tych równań.
Do znalezienia rozwiązania z dowolną dokładnością można wykorzystać metodę Newtona oraz podział wielomianu schematem Hornera, gdy uda nam się znaleźć pierwiastek przybliżony. W efekcie otrzymamy równanie niższego stopnia. Korzystamy tutaj z tej samej procedury, którą stosowaliśmy dla równań 3-go i 4-go stopnia:
Zwróć uwagę, iż takie podejście pozwala rozwiązać równanie stopnia n, jeśli potrafimy rozwiązać równanie stopnia n - 1. Dodatkowo pamiętaj, iż równania o stopniach nieparzystych posiadają zawsze co najmniej jeden pierwiastek rzeczywisty.
![]() |
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:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.