|
Serwis Edukacyjny Nauczycieli I-LO w Tarnowie
Materiały dla uczniów liceum |
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
W naszym serwisie jest nowszy artykuł o obliczaniu pierwiastków funkcji: "Metody numeryczne".
| SPIS TREŚCI |
| Podrozdziały |
Miejscem zerowym (ang. root,
solution) funkcji
|
x0
jest miejscem zerowym wtedy i tylko wtedy, gdy |
|
Uwaga:
Często uczniowie (nawet ci lepsi) mylą to proste pojęcie i twierdzą, iż miejsce zerowe to argument |
Przykład:
Funkcja

Miejsce zerowe często nazywamy pierwiastkiem funkcji (ang. function root).
Funkcja może posiadać więcej niż jeden pierwiastek:
Przykład:
Funkcja

Funkcja może posiadać nieskończenie wiele pierwiastków:
Przykład:
Funkcja
Graficznie miejsce zerowe funkcji możemy interpretować jako punkt przecięcia osi współrzędnych OX przez wykres funkcji:

Znajdowanie miejsc zerowych ma olbrzymie znaczenie w matematyce, fizyce, astronomii, technice itp. Dlatego już dawno temu matematycy opracowali wiele metod rozwiązywania tego zagadnienia. Zasadniczo istnieją dwa podejścia:
W obliczeniach komputerowych będziemy wykorzystywali liczby rzeczywiste. Takie liczby są kodowane w specjalnym systemie zwanym binarnym kodem zmiennoprzecinkowym (ang. binary floating point code). Dokładny opis systemów zmiennoprzecinkowych znajdziesz w artykule o binarnym kodowaniu liczb. Cechą charakterystyczną kodów binarnych stosowanych w obliczeniach komputerowych jest ich skończoność. Oznacza to, iż do reprezentacji liczby komputer wykorzystuje stałą liczbę bitów (np. 8, 16, 32, 64 itp.). W wyniku kod binarny może reprezentować ograniczoną ilość liczb. Na przykład kod naturalny 8-bitowy może przedstawić tylko 256 różnych liczb poczynając od 0, a kończąc na 255. Oto proste przykłady:
C++// Program demonstruje przekroczenie
// zakresu liczby 8-bitowej
//----------------------------------
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
cout << (unsigned)(unsigned char) 257
<< endl << endl;
system("pause");
return 0;
}
|
Pascal// Program demonstruje przekroczenie // zakresu liczby 8-bitowej //---------------------------------- program test; begin writeln(byte(257)); readln; end. |
Python
(dodatek)# Program demonstruje przekroczenie
# zakresu liczby 8-bitowej
#----------------------------------
# Wynik ograniczamy do 8 bitów
print(0b100000001 & 0b11111111)
input("Naciśnij Enter...")
|
Program powinien wypisać liczbę 257, wypisuje natomiast 1. Dlaczego tak się dzieje? Otóż liczba 257 musi być reprezentowana przez 9 bitów:
| 100000001(2) = 257(10). |
Jednakże kod ten obcinamy do 8 bitów (to właśnie dokonują konwersje zastosowane w programach). W efekcie otrzymujemy:
| 100000001(2) → 00000001(2) = 1(10). |
W przypadku liczb zmiennoprzecinkowych istotnym parametrem jest precyzja,
czyli dokładność przedstawienia liczby. Określa ona ile początkowych cyfr liczby
zostanie zapamiętanych dokładnie. Na przykład kod zmiennoprzecinkowy
C++// Program demonstruje przekroczenie
// precyzji liczby zmiennoprzecinkowej
//------------------------------------
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main()
{
// Końcówka ...123 nie
// zostanie zapamiętana!!!
float a = 10000000123;
// 0 cyfr po przecinku
cout << setprecision(0)
// format stałoprzecinkowy
<< fixed;
cout << a << endl << endl;
system("pause");
return 0;
}
|
Pascal// Program demonstruje przekroczenie // precyzji liczby zmiennoprzecinkowej //------------------------------------ program Project2; var a : single; begin // Końcówka ...123 nie // zostanie zapamiętana!!! a := 10000000123; writeln(a:12:0); readln; end. |
Python
(dodatek)# Program demonstruje przekroczenie
# precyzji liczby zmiennoprzecinkowej
#------------------------------------
import struct
# Konwertujemy na 4-bajtowy typ float
# Końcówka ...123 nie
# zostanie zapamiętana!!!
a = struct.pack('f', 10000000123.0)
# Konwertujemy z powrotem na standardowy
# 8-bajtowy typ float
a = struct.unpack('f', a)[0]
# Wyświetlamy wynik konwersji
print("%.f" % a)
input("Naciśnij Enter...")
|
W powyższych przykładach zmienna a zapamiętuje tylko 8 najbardziej znaczących cyfr liczby. Dlatego cyfry końcowe 123 nie zostają poprawnie wyświetlone - liczba jest pamiętana przez komputer jako liczba przybliżona. Oczywiście można przyjąć do zapisu liczb system 64-bitowy (double). Wtedy precyzja wzrośnie do około 15 cyfr najbardziej znaczących, ale problem wciąż będzie występował, tyle że na dalszym miejscu w ciągu cyfr liczby. Do obliczeń zmiennoprzecinkowych należy stosować typ double, który jest typem 64-bitowym (8 bajtów).
Komputer zapamiętuje liczby ze skończoną dokładnością. Konsekwencje są olbrzymie! Spójrz na poniższe dwa przykłady:
C++// Program demonstruje
// błędy zaokrągleń
//--------------------
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
double a = 0;
for(int i = 0; i < 10; i++)
a += 0.1;
cout << ((a == 1.0)
? "WSZYSTKO OK :)" :
"NIE JEST OK :(")
<< endl << endl;
system("pause");
return 0;
}
|
Pascal// Program demonstruje
// błędy zaokrągleń
//--------------------
program Test;
var
a : double;
i : integer;
begin
a := 0;
for i := 1 to 10 do
a := a + 0.1;
if a = 1.0 then
writeln('WSZYSTKO OK :)')
else
writeln('NIE JEST OK :(');
readln;
end.
|
Python
(dodatek)# Program demonstruje
# błędy zaokrągleń
#--------------------
a = 0.0
for i in range(10):
a += 0.1
if a == 1.0:
print("WSZYSTKO OK :)")
else:
print("NIE JEST OK :(")
print("a = %.20f" % a)
input("Naciśnij Enter...")
|
Program tworzy zmienną a i zapamiętuje w niej wartość
0. Następnie dodaje do a dziesięć razy wartość 0.1 i na końcu sprawdza, czy zawartość zmiennej
a jest równa 1. Jeśli tak, wypisuje tekst
| 0 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 + 1/10 = 1 |
Otóż nie.
Komputer pracuje wewnętrznie w systemie dwójkowym. Ułamek dziesiętny 0.1 posiada w systemie dwójkowym następujące rozwinięcie (sposób konwersji liczby dziesiętnej na dwójkową znajdziesz w artykule o binarnym kodowaniu liczb):
| 0,1(10) = 0,0001100110011001100110011001100110011001100110011001100...(2) |
Jest to zatem ułamek okresowy nieskończony (podobną
własność posiada ułamek
Teraz taką przybliżoną wartość dodajemy 10 razy do zmiennej a. Czy otrzymamy 1? Nie,
otrzymamy liczbę bardzo bliską 1, lecz różną od 1. Dla komputera jest to już
zupełnie inna liczba, zatem porównanie daje wynik negatywny i w efekcie komputer
wyświetli ten drugi napis
Zwróć uwagę, iż nawet w tak prostych sytuacjach mogą pojawić się problemy. Jest to swego rodzaju pułapka na niedouczonych programistów i jakże często w nią wpadają!
|
Zapamiętaj:
Wartości zmiennoprzecinkowych (szczególnie uzyskanych w wyniku obliczeń) nie wolno ze sobą bezpośrednio porównywać za pomocą operatora równości. |
Co zatem mamy zrobić? Otóż zamiast przyrównywać wartość zmiennoprzecinkową do innej wartości (gdzie obie mogą być przybliżone) będziemy sprawdzać, czy obie są sobie dostatecznie bliskie. Innymi słowy należy sprawdzić, czy jedna wartość zmiennoprzecinkowa wpada w dostatecznie małe otoczenie drugiej. W tym celu wystarczy przetestować wartość bezwzględną ich różnicy (interpretowaną jako odległość pomiędzy nimi):
| Wartość a jest równa wartości
b z dokładnością do ε wtedy i tylko wtedy, gdy: |
Zapamiętaj to proste rozwiązanie, gdyż znakomicie ułatwi ci ono poruszanie się w gąszczu wyników zmiennoprzecinkowych. Podane poprzednio programy należy odpowiednio zmodyfikować, np. tak:
C++// Pozbycie się błędów
// zaokrągleń
//--------------------
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
int main()
{
double a = 0, e=0.0001;
for(int i = 0; i < 10; i++)
a += 0.1;
cout << (fabs(a - 1.0) < e ?
"WSZYSTKO OK :)" :
"NIE JEST OK :(")
<< endl << endl;
system("pause");
return 0;
}
|
Pascal// Pozbycie się błędów
// zaokrągleń
//--------------------
program Test;
var
a,e : double;
i : integer;
begin
a := 0;
e := 0.0001;
for i := 1 to 10 do
a := a + 0.1;
if abs(a - 1.0) < e then
writeln('WSZYSTKO OK :)')
else
writeln('NIE JEST OK :(');
readln;
end.
|
Python
(dodatek)# Pozbycie się błędów
# zaokrągleń
#--------------------
a = 0.0
e = 0.0001
for i in range(10):
a += 0.1
if abs(a - 1.0) < e:
print("WSZYSTKO OK :)")
else:
print("NIE JEST OK :(")
input("Naciśnij Enter...")
|
Prezentowane w artykule algorytmy wzbogaciliśmy o proste przykłady programów w poniższych środowiskach programowania:
Wszystkie są darmowo dostępne poprzez sieć Internet. Ostatni język, JavaScript, jest dostępny w większości przeglądarek internetowych - Internet Explorer, FireFox, Google Chrome, Opera, Safari.
|
Uwaga:
Przykładowe programy nie są celem tego artykułu - stanowią jedynie proste przykłady implementacji omawianych w artykule algorytmów. |
![]() |
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.