From 5d82188aca1d41af2972a9a86995eea182d96c9b Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Sun, 27 Oct 2024 22:07:03 +0100 Subject: [PATCH] break lines in text --- l1/sprawozdanie.tex | 206 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 169 insertions(+), 37 deletions(-) diff --git a/l1/sprawozdanie.tex b/l1/sprawozdanie.tex index de0a162..95fda03 100644 --- a/l1/sprawozdanie.tex +++ b/l1/sprawozdanie.tex @@ -14,7 +14,9 @@ \textbf{Zad. 1} -Wyznaczanie iteracyjnie epsilonów maszynowych, liczb maszynowych $eta$ i maksymalnych wartości dla wszystkich dostępnych typów zmiennopozycyjnych zgodnych ze standardem IEEE 754 +Wyznaczanie iteracyjnie epsilonów maszynowych, liczb maszynowych +$eta$ i maksymalnych wartości dla wszystkich dostępnych typów +zmiennopozycyjnych zgodnych ze standardem IEEE 754 \vspace{0.5cm} @@ -22,15 +24,26 @@ Wyznaczanie iteracyjnie epsilonów maszynowych, liczb maszynowych $eta$ i maksym \vspace{0.25cm} -Epsilon maszynowy to najmniejsza wartość dla danego typu zmiennopozycyjnego, dla której spełniona jest następująca nierówność: $1.0 + \varepsilon > 1.0$. Innymi słowami, jest to wartość, która po dodaniu do liczby da nam następną liczbę po niej. Epsilon maszynowy jest odwrotnie proporcjonalny do precyzji typu zmiennopozycyjnego, w którym operujemy. +Epsilon maszynowy to najmniejsza wartość dla danego typu +zmiennopozycyjnego, dla której spełniona jest następująca +nierówność: $1.0 + \varepsilon > 1.0$. Innymi słowami, +jest to wartość, która po dodaniu do liczby da nam następną +liczbę po niej. Epsilon maszynowy jest odwrotnie proporcjonalny +do precyzji typu zmiennopozycyjnego, w którym operujemy. \vspace{0.25cm} -Epsilon liczę zaczynając od wartości $1.0$ dla danego typu i dzieląc ją przez $2.0$ dopóki $1.0 + \frac{\varepsilon}{2.0} > 1.0$. Podzielenie $\varepsilon$ przez $2.0$ w warunku pętli powoduje wyjście z pętli po otrzymaniu najmniejszej wartości, dla której warunek jest spełniony. +Epsilon liczę zaczynając od wartości $1.0$ dla danego typu i +dzieląc ją przez $2.0$ dopóki $1.0 + \frac{\varepsilon}{2.0} > 1.0$. +Podzielenie $\varepsilon$ przez $2.0$ w warunku pętli powoduje +wyjście z pętli po otrzymaniu najmniejszej wartości, +dla której warunek jest spełniony. \vspace{0.25cm} -Porównanie wartości $\varepsilon$ liczonych iteracyjnie, za pomocą funkcji $eps()$ z Julii oraz z headera $\langle float.h \rangle$ biblioteki standardowej języka C: +Porównanie wartości $\varepsilon$ liczonych iteracyjnie, +za pomocą funkcji $eps()$ z Julii oraz z headera +$\langle float.h \rangle$ biblioteki standardowej języka C: \begin{table}[h] \begin{adjustbox}{max width=\textwidth} @@ -45,11 +58,14 @@ Porównanie wartości $\varepsilon$ liczonych iteracyjnie, za pomocą funkcji $e \end{adjustbox} \end{table} -Brak wartości Float16 dla headera $\langle float.h \rangle$ wynika z braku 16-bitowego typu zmiennopozycyjnego w standardzie języka C. +Brak wartości Float16 dla headera $\langle float.h \rangle$ +wynika z braku 16-bitowego typu zmiennopozycyjnego w standardzie języka C. \vspace{0.25cm} -Wartości wyliczone iteracyjnie są identyczne do tych z bibliotek standardowych języków Julia i C, więc jeśli ufamy twórcom tych języków, metoda iteracyjna jest wystarczająco dokładna. +Wartości wyliczone iteracyjnie są identyczne do tych z +bibliotek standardowych języków Julia i C, więc jeśli ufamy +twórcom tych języków, metoda iteracyjna jest wystarczająco dokładna. \vspace{0.5cm} @@ -57,13 +73,21 @@ Wartości wyliczone iteracyjnie są identyczne do tych z bibliotek standardowych \vspace{0.25cm} -Liczba maszynowa eta to najmniejsza zdenormalizowana wartość dla danego typu zmiennopozycyjnego większa od $0.0$. +Liczba maszynowa eta to najmniejsza zdenormalizowana +wartość dla danego typu zmiennopozycyjnego większa od $0.0$. \vspace{0.25cm} -Liczbę eta liczę podobnie do liczby maszynowej epsilon – zaczynam od wartości $1.0$ i dzielę ją przez $2.0$ dopóki warunek $\frac{\eta}{2.0} > 0.0$ jest spełniony. Tak samo jak poprzednio podzielenie $\eta$ przez $2.0$ powoduje wyjście z pętli po otrzymaniu najmniejszej wartości, dla której warunek jest spełniony. +Liczbę eta liczę podobnie do liczby maszynowej epsilon – +zaczynam od wartości $1.0$ i dzielę ją przez $2.0$ dopóki +warunek $\frac{\eta}{2.0} > 0.0$ jest spełniony. +Tak samo jak poprzednio podzielenie $\eta$ przez $2.0$ +powoduje wyjście z pętli po otrzymaniu najmniejszej +wartości, dla której warunek jest spełniony. -Porównanie wartości $\eta$ liczonych iteracyjnie, za pomocą $nextfloat(0.0)$ z Julii oraz wartościami zwróconymi przez funkcję $floatmin()$ dla danego typu zmiennopozycyjnego: +Porównanie wartości $\eta$ liczonych iteracyjnie, za +pomocą $nextfloat(0.0)$ z Julii oraz wartościami zwróconymi +przez funkcję $floatmin()$ dla danego typu zmiennopozycyjnego: \begin{table}[h] \begin{adjustbox}{max width=\textwidth} @@ -78,7 +102,12 @@ Porównanie wartości $\eta$ liczonych iteracyjnie, za pomocą $nextfloat(0.0)$ \end{adjustbox} \end{table} -Wartości wyliczone iteracyjnie są identyczne do tych zwróconych przez funkcję $nextfloat(0.0)$, ale $floatmin()$ zwraca wartości o wiele większe. Jest tak dlatego, że ta funkcja zwraca wartości znormalizowane, a metoda iteracyjna i funkcja $nextfloat(0.0)$ zwracają wartości zdenormalizowane - takie, których cecha składa się z samych bitów 0. +Wartości wyliczone iteracyjnie są identyczne do tych +zwróconych przez funkcję $nextfloat(0.0)$, ale $floatmin()$ +zwraca wartości o wiele większe. Jest tak dlatego, że ta +funkcja zwraca wartości znormalizowane, a metoda iteracyjna +i funkcja $nextfloat(0.0)$ zwracają wartości zdenormalizowane +- takie, których cecha składa się z samych bitów 0. \vspace{0.5cm} @@ -86,15 +115,31 @@ Wartości wyliczone iteracyjnie są identyczne do tych zwróconych przez funkcj \vspace{0.5cm} -Wartość maksymalną dla danego typu zmiennopozycyjnego liczę zaczynając od $1.0$ dla tego typu. Następnie mnożę tą wartość przez $2.0$ dopóki $max \cdot 2.0 < \infty$ (sprawdzam tę nierówność korzystając z funkcji $isfinite()$). Osiągnięta w ten sposób wartość niekoniecznie jest maksymalna, żeby to zmienić tworzę pomocniczą zmienną $x$, której na początku przypisuję wartość $\frac{max}{2.0}$. Następnie, dopóki $max + x < \infty$ dodaję $x$ do $max$ i dzielę $x$ przez $2.0$. +Wartość maksymalną dla danego typu zmiennopozycyjnego +liczę zaczynając od $1.0$ dla tego typu. Następnie +mnożę tą wartość przez $2.0$ dopóki $max \cdot 2.0 < \infty$ +(sprawdzam tę nierówność korzystając z funkcji $isfinite()$). +Osiągnięta w ten sposób wartość niekoniecznie jest maksymalna, +żeby to zmienić tworzę pomocniczą zmienną $x$, której na początku +przypisuję wartość $\frac{max}{2.0}$. Następnie, dopóki +$max + x < \infty$ dodaję $x$ do $max$ i dzielę $x$ przez $2.0$. \vspace{0.25cm} -W przypadku gdyby w ostatniej iteracji pierwszej pętli $max$ nie był maksymalny, ale $max \cdot 2.0$ był nieskończony, zostało nam co najwyżej $max \cdot 2.0 - \varepsilon$ do "`dopełnienia"'. Zaczynamy to "`dopełnianie"' od $\frac{max}{2.0}$ – wiemy, że $max + max = max \cdot 2.0$ będzie nieskończone. W każdej iteracji dodajemy $x$ do $max$ i dzielimy $x$ przez $2.0$. W ten sposób "`dopełnimy"' $max$ do końca i otrzymamy rzeczywistą wartość maksymalną. +W przypadku gdyby w ostatniej iteracji pierwszej pętli $max$ +nie był maksymalny, ale $max \cdot 2.0$ był nieskończony, +zostało nam co najwyżej $max \cdot 2.0 - \varepsilon$ do +"`dopełnienia"'. Zaczynamy to "`dopełnianie"' od $\frac{max}{2.0}$ +– wiemy, że $max + max = max \cdot 2.0$ będzie nieskończone. +W każdej iteracji dodajemy $x$ do $max$ i dzielimy $x$ przez $2.0$. +W ten sposób "`dopełnimy"' $max$ do końca i otrzymamy +rzeczywistą wartość maksymalną. \vspace{0.25cm} -Porównanie wartości maksymalnych liczonych iteracyjnie, za pomocą funkcji $floatmax()$ z Julii oraz z headera $\langle float.h \rangle$ biblioteki standardowej języka C: +Porównanie wartości maksymalnych liczonych iteracyjnie, +za pomocą funkcji $floatmax()$ z Julii oraz z headera +$\langle float.h \rangle$ biblioteki standardowej języka C: \begin{table}[h] \begin{adjustbox}{max width=\textwidth} @@ -109,25 +154,33 @@ Porównanie wartości maksymalnych liczonych iteracyjnie, za pomocą funkcji $fl \end{adjustbox} \end{table} -Brak wartości Float16 dla headera $\langle float.h \rangle$ wynika z braku 16-bitowego typu zmiennopozycyjnego w standardzie języka C. +Brak wartości Float16 dla headera $\langle float.h \rangle$ +wynika z braku 16-bitowego typu zmiennopozycyjnego w standardzie języka C. \vspace{0.25cm} -Wartości wyznaczone iteracyjnie są identyczne do tych zwróconych przez $floatmax()$ jak i tych z headera $\langle float.h \rangle$ z biblioteki standardowej języka C. +Wartości wyznaczone iteracyjnie są identyczne do tych +zwróconych przez $floatmax()$ jak i tych z headera +$\langle float.h \rangle$ z biblioteki standardowej języka C. \vspace{0.5cm} \textbf{Zad. 2} -Eksperymentalne sprawdzenie słuszności twierdzenia Kahana dla wszystkich typów zmiennopozycyjnych dostępnych w języku Julia. +Eksperymentalne sprawdzenie słuszności twierdzenia Kahana dla +wszystkich typów zmiennopozycyjnych dostępnych w języku Julia. \vspace{0.25cm} -Twierdzenie Kahana mówi, że epsilon maszynowy można uzyskać w następujący sposób: $\varepsilon = 3(4/3 - 1) / 1$. Aby sprawdzić wyniki korzystam z funkcji $eps()$ z biblioteki standardowej Julii. +Twierdzenie Kahana mówi, że epsilon maszynowy można +uzyskać w następujący sposób: $\varepsilon = 3(4/3 - 1) / 1$. +Aby sprawdzić wyniki korzystam z funkcji +$eps()$ z biblioteki standardowej Julii. \vspace{0.25cm} -Porównanie wartości epsilonu maszynowego liczonego za pomocą twierdzenia Kahana oraz za pomocą funkcji $eps()$: +Porównanie wartości epsilonu maszynowego liczonego za +pomocą twierdzenia Kahana oraz za pomocą funkcji $eps()$: \begin{table}[h] \begin{adjustbox}{max width=\textwidth} @@ -142,25 +195,46 @@ Porównanie wartości epsilonu maszynowego liczonego za pomocą twierdzenia Kaha \end{adjustbox} \end{table} -Dla typu $Float32$ wartości są identyczne, dla typów $Float16$ i $Float64$ wartości różnią się znakiem - twierdzenie Kahana daje nam wartości ujemne. Wynika to z definicji typów zmiennoprzecinkowych i rozwinięcia liczby $4/3$ binarnie – $1.(10)$. Typy $Float16$, $Float32$ i $Float64$ mają odpowiednio 10, 23 i 52 bity mantysy. Rozwijając $4/3$, na indeksach parzystych dostajemy bit 0, na nieparzystych bit 1. W typach o parzystej ilości bitów w mantysie ($Float16$ i $Float64$) na ostatnim indeksie będzie 0. Mnożąc wartość $4/3 - 1$ przez $3$ otrzymamy wartość minimalnie mniejszą od $1$ Przez co wynik jest ujemny. Z kolei dla typu $Float32$ ostatnim bitem będzie 1, co da nam wartość dodatnią. +Dla typu $Float32$ wartości są identyczne, dla typów +$Float16$ i $Float64$ wartości różnią się znakiem - +twierdzenie Kahana daje nam wartości ujemne. Wynika +to z definicji typów zmiennoprzecinkowych i rozwinięcia +liczby $4/3$ binarnie – $1.(10)$. Typy $Float16$, $Float32$ i +$Float64$ mają odpowiednio 10, 23 i 52 bity mantysy. +Rozwijając $4/3$, na indeksach parzystych dostajemy bit 0, +na nieparzystych bit 1. W typach o parzystej ilości bitów +w mantysie ($Float16$ i $Float64$) na ostatnim indeksie będzie 0. +Mnożąc wartość $4/3 - 1$ przez $3$ otrzymamy wartość minimalnie +mniejszą od $1$ Przez co wynik jest ujemny. Z kolei dla typu +$Float32$ ostatnim bitem będzie 1, co da nam wartość dodatnią. \vspace{0.25cm} -Twierdzenie Kahana poprawnie liczy epsilon maszynowy jednak trzeba pamiętać o wzięciu modułu z wyniku. +Twierdzenie Kahana poprawnie liczy epsilon maszynowy +jednak trzeba pamiętać o wzięciu modułu z wyniku. \vspace{0.5cm} \textbf{Zad. 3} -Eksperymentalne sprawdzenie rozmieszczenia liczb zmiennopozycyjnych w arytmetyce $Float64$ w języku Julia. +Eksperymentalne sprawdzenie rozmieszczenia liczb +zmiennopozycyjnych w arytmetyce $Float64$ w języku Julia. \vspace{0.25cm} -Aby sprawdzić, czy liczby w przedziale $[1, 2]$ są równomiernie rozmieszczone można zrobić pętlę, w której od $1.0$ do $2.0$ jedną liczbę iterujemy dodając do niej krok $\delta = 2^{-52}$, drugą korzystając z funkcji $nextfloat()$ jednak jest to bardzo nieefektywna metoda. +Aby sprawdzić, czy liczby w przedziale $[1, 2]$ są +równomiernie rozmieszczone można zrobić pętlę, +w której od $1.0$ do $2.0$ jedną liczbę iterujemy +dodając do niej krok $\delta = 2^{-52}$, drugą korzystając +z funkcji $nextfloat()$ jednak jest to bardzo nieefektywna metoda. \vspace{0.25cm} -Lepszą metodą jest sprawdzenie pierwszej i ostatniej liczby z przedziału, w naszym przypadku $nextfloat(1.0)$ i $nextfloat(2.0)$. Sprawdzamy cechę obu – jeśli są różne, wyklucza to równomierne rozmieszczenie liczb. W przeciwnym przypadku możemy obliczyć $\delta$ w następujący sposób: +Lepszą metodą jest sprawdzenie pierwszej i ostatniej +liczby z przedziału, w naszym przypadku $nextfloat(1.0)$ +i $nextfloat(2.0)$. Sprawdzamy cechę obu – jeśli są różne, +wyklucza to równomierne rozmieszczenie liczb. W przeciwnym +przypadku możemy obliczyć $\delta$ w następujący sposób: \[2^{cecha - 1023} \cdot 2^{-52}\] @@ -179,21 +253,40 @@ gdzie 1023 to przesunięcie cechy typu $Float64$, a 52 to rozmiar mantysy. \end{adjustbox} \end{table} -Dla przedziału [1.0, 2.0] rzeczywiście $\delta = 2^{-52}$, z kolei $\delta$ dla przedziałów [0.5, 1.0] i [2.0, 4.0] pokazuje, że jest ona zależna od cechy liczb z zakresu nad którym się skupiamy. Im bliżej zera jesteśmy tym mniejsza jest $\delta$ – zwiększa się dokładność liczb. Analogicznie oddalając się od zera tracimy precyzję części ułamkowej – przy coraz większych liczbach prawdopodobnie bardziej obchodzi nas część całkowita. +Dla przedziału [1.0, 2.0] rzeczywiście $\delta = 2^{-52}$, +z kolei $\delta$ dla przedziałów [0.5, 1.0] i [2.0, 4.0] +pokazuje, że jest ona zależna od cechy liczb z zakresu +nad którym się skupiamy. Im bliżej zera jesteśmy tym mniejsza +jest $\delta$ – zwiększa się dokładność liczb. Analogicznie +oddalając się od zera tracimy precyzję części ułamkowej – +przy coraz większych liczbach prawdopodobnie bardziej obchodzi nas część całkowita. \vspace{0.5cm} \textbf{Zad. 4} -Eksperymentalne znalezienie liczby w arytmetyce $Float64$ w przedziale $(1, 2)$ takiej, że $x \cdot (1/x) \neq 1$ oraz znalezienie najmniejszej takiej liczby. +Eksperymentalne znalezienie liczby w arytmetyce $Float64$ w +przedziale $(1, 2)$ takiej, że $x \cdot (1/x) \neq 1$ oraz +znalezienie najmniejszej takiej liczby. \vspace{0.25cm} -Implementacja zadania opiera się na funkcji $nextfloat()$ z języka Julia. Zaczynamy od $nextfloat(1.0)$, iterujemy do $2.0$. W każdej iteracji liczymy wynik $x \cdot (1/x)$, jeśli jest różny od $1.0$ zwracamy $x$ jako wynik. Oczywiście jest to również najmniejsza taka liczba. +Implementacja zadania opiera się na funkcji $nextfloat()$ z +języka Julia. Zaczynamy od $nextfloat(1.0)$, iterujemy do +$2.0$. W każdej iteracji liczymy wynik $x \cdot (1/x)$, +jeśli jest różny od $1.0$ zwracamy $x$ jako wynik. +Oczywiście jest to również najmniejsza taka liczba. \vspace{0.25cm} -Najmniejsza taka liczba to $1.000000057228997$. Błędny wynik wyrażenia, które zawsze powinno zwracać $1.0$ jest spowodowany oczywiście skończoną mantysą w liczbach zmiennoprzecinkowych – przez co tracimy precyzję – ale również kolejnością wykonywania działań. Gdyby zamienić $x \cdot (1/x)$ na $(x \cdot 1) / x$ zawsze dostalibyśmy odpowiedni wynik – $x \cdot 1$ nie zmieniłoby wartości liczby, a $x / x$ zakładając dobrze napisany interpreter lub kompilator zawsze zwróci $1.0$ +Najmniejsza taka liczba to $1.000000057228997$. Błędny wynik +wyrażenia, które zawsze powinno zwracać $1.0$ jest spowodowany +oczywiście skończoną mantysą w liczbach zmiennoprzecinkowych +– przez co tracimy precyzję – ale również kolejnością wykonywania +działań. Gdyby zamienić $x \cdot (1/x)$ na $(x \cdot 1) / x$ +zawsze dostalibyśmy odpowiedni wynik – $x \cdot 1$ nie +zmieniłoby wartości liczby, a $x / x$ zakładając dobrze +napisany interpreter lub kompilator zawsze zwróci $1.0$ \vspace{0.5cm} @@ -218,11 +311,15 @@ na 4 sposoby: \vspace{0.25cm} -(c) od największego do najmniejszego – liczenie częściowych sum elementów dodatnich i ujemnych w porządku malejącym względem wartości absolutnej liczb, następnie dodanie do siebie sum częściowych +(c) od największego do najmniejszego – liczenie częściowych +sum elementów dodatnich i ujemnych w porządku malejącym względem +wartości absolutnej liczb, następnie dodanie do siebie sum częściowych \vspace{0.25cm} -(d) od największego do najmniejszego – liczenie częściowych sum elementów dodatnich i ujemnych w porządku rosnącym względem wartości absolutnej liczb, następnie dodanie do siebie sum częściowych +(d) od największego do najmniejszego – liczenie częściowych +sum elementów dodatnich i ujemnych w porządku rosnącym względem +wartości absolutnej liczb, następnie dodanie do siebie sum częściowych \vspace{0.25cm} @@ -230,11 +327,13 @@ używając typów zmiennopozycyjnych $Float32$ i $Float64$. \vspace{0.25cm} -Oczekiwanym wynikiem iloczynu skalarnego na tych dwóch wektorach jest $-1.00657107000000 \cdot 10^{-11}$. +Oczekiwanym wynikiem iloczynu skalarnego na tych +dwóch wektorach jest $-1.00657107000000 \cdot 10^{-11}$. \vspace{0.25cm} -Porównanie wyników iloczynu skalarnego przeprowadzonego za pomocą powyższych czterech sposobów: +Porównanie wyników iloczynu skalarnego przeprowadzonego +za pomocą powyższych czterech sposobów: \begin{table}[h] \begin{adjustbox}{max width=\textwidth} @@ -250,7 +349,11 @@ Porównanie wyników iloczynu skalarnego przeprowadzonego za pomocą powyższych \end{adjustbox} \end{table} -Żaden ze sposobów nie dał wyniku bliskiego oczekiwanemu, choć sposób (b) w arytmetyce $Float64$ dał wynik dość bliski prawdzie. Patrząc na wyniki korzystające z różnych sposobów widzimy również, że kolejność wykonywania działań może znacznie wpłynąć na poprawność wyniku. +Żaden ze sposobów nie dał wyniku bliskiego oczekiwanemu, +choć sposób (b) w arytmetyce $Float64$ dał wynik dość +bliski prawdzie. Patrząc na wyniki korzystające z różnych +sposobów widzimy również, że kolejność wykonywania działań +może znacznie wpłynąć na poprawność wyniku. \vspace{0.5cm} @@ -300,13 +403,25 @@ Porównanie wyników dla obu funkcji: \end{adjustbox} \end{table} -Już przy $x = 8^{-9}$, $f(x)$ przyjmuje wartość $0.0$, którą zachowuje przy mniejszych wartościach. Przy wartościach większych od $8^{-9}$ obie funkcje mają podobne wartości. $f(x)$ szybciej traci precyzję i spada do $0.0$ przez odejmowanie $1.0$ od pierwiastka – im mniejsza wartość $x$ tym bliżej $x^2 + 1$ jest $1.0$. Przez pierwiastek całe wyrażenie zbliża się jeszcze bardziej do $1.0$, od którego również odejmujemy $1.0$. Przekształcenie $f(x)$ w $g(x)$ zwalcza ten problem poprzez pozbycie się problematycznego odejmowania, dzięki czemu tracimy mniej precyzji wykonując działania. +Już przy $x = 8^{-9}$, $f(x)$ przyjmuje wartość $0.0$, +którą zachowuje przy mniejszych wartościach. Przy +wartościach większych od $8^{-9}$ obie funkcje mają +podobne wartości. $f(x)$ szybciej traci precyzję i +spada do $0.0$ przez odejmowanie $1.0$ od pierwiastka +– im mniejsza wartość $x$ tym bliżej $x^2 + 1$ jest $1.0$. +Przez pierwiastek całe wyrażenie zbliża się jeszcze bardziej +do $1.0$, od którego również odejmujemy $1.0$. +Przekształcenie $f(x)$ w $g(x)$ zwalcza ten problem +poprzez pozbycie się problematycznego odejmowania, +dzięki czemu tracimy mniej precyzji wykonując działania. \vspace{0.5cm} \textbf{Zad. 7} -Obliczanie przybliżonej wartości pochodnej funkcji $f(x) = \sin{x} + \cos{3x}$ w punkcie $x_0 = 1$ oraz błędów $|f^{'}(x_0) - \widetilde{f^{'}}(x_0)|$ korzystając ze wzoru +Obliczanie przybliżonej wartości pochodnej funkcji +$f(x) = \sin{x} + \cos{3x}$ w punkcie $x_0 = 1$ oraz +błędów $|f^{'}(x_0) - \widetilde{f^{'}}(x_0)|$ korzystając ze wzoru \[f^{'}(x_0) \approx \widetilde{f^{'}}(x_0) = \frac{f(x_0 + h) - f(x_0)}{h}\] @@ -381,11 +496,23 @@ Dokładna wartość pochodnej dla $x_0 = 1$ to $0.11694228168853815$. \hline \end{longtable} -Najdokładniejszy wynik jest dla $n = 28$, $h = 2^{-28}$, dokładnie po środku wartości testowanych (jeśli zignorujemy 54, dla którego wynik jest identyczny do 53). Idąc w górę lub w dół błąd jest coraz większy, dla $n = 53$ dochodząc do wartości pochodnej. +Najdokładniejszy wynik jest dla $n = 28$, $h = 2^{-28}$, +dokładnie po środku wartości testowanych (jeśli zignorujemy +54, dla którego wynik jest identyczny do 53). Idąc w górę lub w dół +błąd jest coraz większy, dla $n = 53$ dochodząc do wartości pochodnej. \vspace{0.25cm} -Wzięcie zbyt dużego $h$ (zbyt małego $n$) powoduje ogromny błąd z definicji pochodnej, którą jest granica wzoru wykorzystanego w tym zadaniu przy h dążącym do 0. Przy coraz mniejszych $h$ (coraz większych $n$) na papierze zbliżamy się do poprawnej wartości, ale w rzeczywistości ograniczona precyzja liczb zmiennopozycyjnych w standardzie IEEE 754 powoduje zwiększanie się błędu, lecz nie do takich rozmiarów jak dla pierwszych kilku $n$. Maksymalny błąd po przekroczeniu $n = 28$ otrzymujemy przy $n = 53$, gdzie $h < \varepsilon$ w precyzji $Float64$. Wtedy +Wzięcie zbyt dużego $h$ (zbyt małego $n$) powoduje ogromny +błąd z definicji pochodnej, którą jest granica wzoru +wykorzystanego w tym zadaniu przy h dążącym do 0. Przy coraz +mniejszych $h$ (coraz większych $n$) na papierze zbliżamy się +do poprawnej wartości, ale w rzeczywistości ograniczona +precyzja liczb zmiennopozycyjnych w standardzie +IEEE 754 powoduje zwiększanie się błędu, lecz nie do +takich rozmiarów jak dla pierwszych kilku $n$. +Maksymalny błąd po przekroczeniu $n = 28$ otrzymujemy +przy $n = 53$, gdzie $h < \varepsilon$ w precyzji $Float64$. Wtedy \[x_0 + h = x_0 = 1\] @@ -399,6 +526,11 @@ zatem dla $n \geq 53$ błąd będzie zawsze równy dokładnej wartości pochodne \textbf{Wnioski z listy} -Liczby zmiennopozycyjne w standardzie IEEE 754 mają skończoną precyzję, co przy liczbach bliskich zeru powoduje błędy. Pisząc kod operujący na tych liczbach musimy pamiętać o tym fakcie i wybrać odpowiedni typ do trzymania danych lub zastanowić się nad trzymaniem ich w typach całkowitych, np. waluty zamiast we floacie trzymać w dwóch integerach. +Liczby zmiennopozycyjne w standardzie IEEE 754 mają skończoną +precyzję, co przy liczbach bliskich zeru powoduje błędy. Pisząc +kod operujący na tych liczbach musimy pamiętać o tym fakcie +i wybrać odpowiedni typ do trzymania danych lub zastanowić +się nad trzymaniem ich w typach całkowitych, +np. waluty zamiast we floacie trzymać w dwóch integerach. \end{document}