MN03LAB: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1: | Linia 1: | ||
<!-- | <!-- | ||
Konwertowane z pliku LaTeX przez latex2mediawiki, zob. http://www.ii.uj.edu.pl/ pawlik1/latex2mediawiki.php | Konwertowane z pliku LaTeX przez latex2mediawiki, zob. http://www.ii.uj.edu.pl/ pawlik1/latex2mediawiki.php. | ||
Niezb�dne rozszerzenia i modyfikacje oryginalnego latex2mediawiki | |||
wprowadzi� przykry@mimuw.edu.pl | |||
--> | --> | ||
= | =Własności arytmetyki zmiennoprzecinkowej= | ||
{{powrot |Metody numeryczne | do strony głównej | |||
przedmiotu <strong>Metody numeryczne</strong>}} | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
Ogl�daj wskaz�wki i rozwi�zania __SHOWALL__<br> | |||
Ukryj wskaz�wki i rozwi�zania __HIDEALL__ | |||
</div> | |||
<div style="margin-top:1em; padding-top,padding-bottom:1em;"> | <div style="margin-top:1em; padding-top,padding-bottom:1em;"> | ||
Linia 10: | Linia 21: | ||
Wyjaśnij, dlaczego w arytmetyce podwójnej precyzji IEEE 754 mamy | Wyjaśnij, dlaczego w arytmetyce podwójnej precyzji IEEE 754 mamy | ||
<div | <div style="font-family: monospace; white-space: pre; border-style: dashed; border-width: thin; border-color: black; margin: 1em; padding:1em; color: #444; background-color:#fdfdfd;"><nowiki>octave:19> 2006/1e309 | ||
octave:19> 2006/1e309 | |||
ans = 0 | ans = 0 | ||
octave:20> 2.006/1e306 | octave:20> 2.006/1e306 | ||
Linia 18: | Linia 27: | ||
octave:21> (2006/1000)/(1e309/1000) | octave:21> (2006/1000)/(1e309/1000) | ||
ans = 0 | ans = 0 | ||
</ | </nowiki></div> | ||
Oczywiście, teoretycznie wszystkie trzy liczby powinny być sobie | Oczywiście, "teoretycznie" wszystkie trzy liczby powinny być sobie | ||
równe (i niezerowe). | równe (i niezerowe). | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | ||
<div style="font-size:smaller; background-color:# | <div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Kluczem jest wyjaśnienie, jaka jest reprezentacja liczby <math>\displaystyle 10^{309}</math> w podwójnej precyzji... A reprezentacja <math>\displaystyle 10^{306}</math>? </div> | ||
<math>\displaystyle 10^{306}</math>? </div> | |||
</div></div> | </div></div> | ||
Linia 36: | Linia 44: | ||
Podaj przykłady <strong>zbieżnych</strong> szeregów postaci <math>\displaystyle \sum_{n=1}^{\infty} a_n</math>, których <math>\displaystyle N</math>-te sumy częściowe | Podaj przykłady <strong>zbieżnych</strong> szeregów postaci <math>\displaystyle \sum_{n=1}^{\infty} a_n</math>, których <math>\displaystyle N</math>-te sumy częściowe | ||
obliczone w arytmetyce pojedynczej precyzji algorytmem | obliczone w arytmetyce pojedynczej precyzji algorytmem | ||
<div | <div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>suma = 0.0; | ||
suma = 0.0; | |||
for n = 1..N | for n = 1..N | ||
suma += <math>\displaystyle a_n</math>; | suma += <math>\displaystyle a_n</math>; | ||
Linia 45: | Linia 51: | ||
będą | będą | ||
* ograniczone niezależnie od <math>\displaystyle N</math>, albo | * ograniczone niezależnie od <math>\displaystyle N</math>, albo | ||
* numerycznie rozbieżne, to znaczy takie, że dla bardzo dużych <math>\displaystyle N</math> zachodzi | * numerycznie rozbieżne, to znaczy takie, że dla bardzo dużych <math>\displaystyle N</math> zachodzi <code style="color: #006">suma == Inf</code>. | ||
<code>suma == Inf</code>. | |||
Wykonaj to samo zadanie, ale podając przykłady szeregów <strong>rozbieżnych</strong> (w | Wykonaj to samo zadanie, ale podając przykłady szeregów <strong>rozbieżnych</strong> (w | ||
Linia 56: | Linia 61: | ||
Rozpatrz na przykład takie szeregi: | Rozpatrz na przykład takie szeregi: | ||
* Szereg zerowy (numerycznie dostajesz oczywiście też 0) | * Szereg zerowy (numerycznie dostajesz oczywiście też 0) | ||
* <math>\displaystyle 1 + 10^{2006} - 10^{2006} + 0 + \ldots = 1</math> oraz <math>\displaystyle 1 + 10^{2006} - 1 + 0 + \ldots = 10^{2006}</math> | * <math>\displaystyle 1 + 10^{2006} - 10^{2006} + 0 + \ldots = 1</math> oraz <math>\displaystyle 1 + 10^{2006} - 1 + 0 + \ldots = 10^{2006}</math> (numerycznie dostaniesz, odpowiednio, <code style="color: #006">NaN</code> (dlaczego?) i <code style="color: #006">Inf</code>. | ||
* Szereg harmoniczny (numerycznie sumy częściowe w pewnym momencie przestaną rosnąć). | |||
(numerycznie dostaniesz, odpowiednio, <code>NaN</code> (dlaczego?) i <code>Inf</code>. | |||
* Szereg harmoniczny (numerycznie sumy częściowe w pewnym momencie przestaną | |||
rosnąć). | |||
* Szereg jedynkowy. | * Szereg jedynkowy. | ||
Linia 69: | Linia 71: | ||
<div class="exercise"> | <div class="exercise"> | ||
Dla kolejnych <math>\displaystyle N</math> wyznacz <math>\displaystyle N</math>-tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy <math>\displaystyle x=-90</math>: | Dla kolejnych <math>\displaystyle N</math>, wyznacz <math>\displaystyle N</math>-tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy <math>\displaystyle x=-90</math>: | ||
<center><math>\displaystyle | <center><math>\displaystyle | ||
e^x \approx \sum_{n=0}^N \frac{x^n}{n!}, | e^x \approx \sum_{n=0}^N \frac{x^n}{n!}, | ||
</math></center> | </math></center> | ||
korzystając z algorytmu podanego w poprzednim zadaniu. | korzystając z algorytmu podanego w poprzednim zadaniu. Oblicz błąd względny | ||
i bezwzględny w porównaniu | i bezwzględny wyznaczonego przybliżenia, w porównaniu | ||
do wartości wyznaczonej z wykorzystaniem funkcji bibliotecznej <code>exp()</code>. Powtórz następnie dla <math>\displaystyle x=10</math>. | do wartości wyznaczonej z wykorzystaniem funkcji bibliotecznej <code>exp()</code>. Powtórz następnie dla <math>\displaystyle x=10</math>. | ||
Linia 103: | Linia 105: | ||
<math>\displaystyle n</math> nie jest dobrym pomysłem. Przeprowadź eksperyment numeryczny potwierdzający | <math>\displaystyle n</math> nie jest dobrym pomysłem. Przeprowadź eksperyment numeryczny potwierdzający | ||
to stwierdzenie i objaśnij jego wyniki. | to stwierdzenie i objaśnij jego wyniki. | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | |||
<div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Kiedy da znać o sobie epsilon maszynowy? </div> | |||
</div></div> | |||
</div></div> | </div></div> | ||
Linia 113: | Linia 120: | ||
arytmetyce podwójnej precyzji przy użyciu poniższego kodu. | arytmetyce podwójnej precyzji przy użyciu poniższego kodu. | ||
<div | <div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>int dlicznik; | ||
double dsuma, dstarasuma; | double dsuma, dstarasuma; | ||
double dskladnik; | double dskladnik; | ||
Linia 133: | Linia 138: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | ||
<div style="font-size:smaller; background-color:# | <div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Policz, ile mniej więcej obrotów pętli potrzeba, by suma przestała rosnąć. </div> | ||
</div></div> | </div></div> | ||
Linia 140: | Linia 145: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> | ||
Nasza suma przekroczy wartość 20, więc aby <code>20 + dskladnik == 20</code>, musi | Nasza suma przekroczy wartość 20, więc aby <code>20 + dskladnik == 20</code>, musi | ||
być dskładnik <math>\displaystyle \approx 10^{-15}</math> (lub więcej). Tymczasem zakres liczb typu integer wynosi | być dskładnik <math>\displaystyle \approx 10^{-15}</math> (lub więcej). Tymczasem zakres liczb typu integer wynosi niewiele ponad <math>\displaystyle 10^9</math>, więc po jakimś czasie <code>dlicznik</code> przyjmie wartości ujemne. | ||
niewiele ponad <math>\displaystyle 10^9</math>, więc po jakimś czasie | |||
Aby doliczyć | <!-- | ||
<code>long long double</code>, | Aby doliczyć "do końca", musielibyśmy licznik potraktować jako liczbę typu | ||
<code>long long double</code>, którego zakres sięga <math>\displaystyle 10^{18}</math>. Ale i tak mielibyśmy | |||
kłopot z doczekaniem do końca działalności programu. | kłopot z doczekaniem do końca działalności programu. | ||
Zakładając optymistycznie, że na sekundę zliczamy <math>\displaystyle 10^7</math> składników, | Zakładając optymistycznie, że na sekundę zliczamy <math>\displaystyle 10^7</math> składników, | ||
potrzebowalibyśmy razem około <math>\displaystyle 10^7</math> sekund, czyli ponad trzy miesiące... | potrzebowalibyśmy razem około <math>\displaystyle 10^7</math> sekund, czyli ponad trzy miesiące... | ||
--> | |||
</div></div></div> | </div></div></div> | ||
< | <!-- | ||
<div style="margin-top:1em; padding-top,padding-bottom:1em;"> | <div style="margin-top:1em; padding-top,padding-bottom:1em;"> | ||
Linia 165: | Linia 164: | ||
<div class="exercise"> | <div class="exercise"> | ||
Dla zadanej liczby <math>\displaystyle a>1</math> należy wyznaczyć przybliżenie <math>\displaystyle \sqrt{a}</math> | Dla zadanej liczby <math>\displaystyle a>1</math> należy wyznaczyć przybliżenie <math>\displaystyle \sqrt{a}</math> stosując metodę Herona. Zaproponuj | ||
dobre przybliżenie początkowe <math>\displaystyle x_0</math> wiedząc, że <math>\displaystyle a</math> jest liczbą maszynową typu | dobre przybliżenie początkowe <math>\displaystyle x_0</math> wiedząc, że <math>\displaystyle a</math> jest liczbą maszynową typu | ||
<code>double</code>. Ile iteracji wystarczy, by osiągnąć <math>\displaystyle \epsilon</math>-zadowalające przybliżenie? | <code>double</code>. Ile iteracji wystarczy, by osiągnąć <math>\displaystyle \epsilon</math>-zadowalające przybliżenie? | ||
Linia 180: | Linia 179: | ||
dla pewnego (znanego) <math>\displaystyle k \in N</math>, przy czym <math>\displaystyle \frac{1}{2} \leq \sqrt{g} \leq 1</math>. | dla pewnego (znanego) <math>\displaystyle k \in N</math>, przy czym <math>\displaystyle \frac{1}{2} \leq \sqrt{g} \leq 1</math>. | ||
Wobec tego obliczenie | Wobec tego, obliczenie | ||
<math>\displaystyle \sqrt{a}</math> wymaga po prostu | <math>\displaystyle \sqrt{a}</math> wymaga po prostu wyznaczenia <math>\displaystyle \sqrt{g}</math>. Najprostsze przybliżenie <math>\displaystyle \sqrt{g}</math> to | ||
<math>\displaystyle \sqrt{g}\approx 1</math>. Błąd takiego przybliżenia to | <math>\displaystyle \sqrt{g}\approx 1</math>. Błąd takiego przybliżenia to | ||
<math>\displaystyle |\sqrt{g} - 1| \leq 0.5</math>. | <math>\displaystyle |\sqrt{g} - 1| \leq 0.5</math>. | ||
Linia 189: | Linia 188: | ||
</div></div></div> | </div></div></div> | ||
--> | |||
<div style="margin-top:1em; padding-top,padding-bottom:1em;"> | <div style="margin-top:1em; padding-top,padding-bottom:1em;"> | ||
<span style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie: Zadanie o wyznaczaniu odwrotności bez dzielenia metodą Newtona</span> | <span style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie: Zadanie o wyznaczaniu odwrotności bez dzielenia metodą Newtona</span> | ||
Linia 206: | Linia 207: | ||
</math></center> | </math></center> | ||
to możemy jako pierwsze przybliżenie wybrać <math>\displaystyle x_0 = \frac{3}{4}2^{-p}</math> | to możemy jako pierwsze przybliżenie wybrać <math>\displaystyle x_0 = \frac{3}{4}2^{-p}</math> (jak | ||
wybrać lepsze <math>\displaystyle x_0</math>? | wybrać jeszcze lepsze <math>\displaystyle x_0</math>?) | ||
Wtedy mamy następujące oszacowania: | Wtedy mamy następujące oszacowania: | ||
Linia 221: | Linia 222: | ||
to, jeśli chcemy, by błąd względny przybliżenia <math>\displaystyle x_{k+1}</math> spełniał <math>\displaystyle \frac{|x_{k+1} - | to, jeśli chcemy, by błąd względny przybliżenia <math>\displaystyle x_{k+1}</math> spełniał <math>\displaystyle \frac{|x_{k+1} - | ||
\frac{1}{a}|}{\frac{1}{a}} = |x_{k+1}a - 1| \leq \epsilon = 2^{-53}</math>, | \frac{1}{a}|}{\frac{1}{a}} = |x_{k+1}a - 1| \leq \epsilon = 2^{-53}</math>, | ||
musimy wykonać co najwyżej <math>\displaystyle 6</math> iteracji. Ponieważ koszt jednej iteracji | musimy wykonać co najwyżej <math>\displaystyle 6</math> iteracji. Ponieważ koszt jednej iteracji | ||
to 3 | to 3 działania arytmetyczne, wyznaczenie odwrotności <math>\displaystyle a</math> byłoby 18 razy droższe od mnożenia i dodawania, które mają podobny koszt. | ||
mnożenia i dodawania, które mają podobny koszt. | |||
Tymczasem we współczesnych realizacjach dzielenie jest tylko około 4 razy droższe od | Tymczasem, we współczesnych realizacjach, dzielenie jest tylko około 4 razy droższe od mnożenia! Możesz sprawdzić, [http://www.cs.utexas.edu/users/moore/publications/divide_paper.pdf jak to się dzieje np. w procesorach AMD]. | ||
mnożenia! Możesz sprawdzić, | |||
[http://www.cs.utexas.edu/users/moore/publications/divide_paper.pdf jak to się dzieje np. w procesorach AMD]. | |||
Więcej na temat implementacji algorytmów dzielenia oraz wyciągania pierwiastka | Więcej na temat implementacji algorytmów dzielenia oraz wyciągania pierwiastka | ||
Linia 247: | Linia 245: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> | ||
Od najmniejszej do największej. | Od najmniejszej do największej. | ||
</div></div></div> | |||
<div style="margin-top:1em; padding-top,padding-bottom:1em;"> | |||
<span style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie</span> | |||
<div class="exercise"> | |||
Dlaczego w algorytmie bisekcji rozwiązywania równania <math>\displaystyle f(x)=0</math>, sprawdzając warunek różnych znaków <math>\displaystyle f</math> w krańcach przedziału <math>\displaystyle [a,b]</math>, używamy kryterium | |||
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>if ( sign(f(x)) != sign(f(xl)) ) | |||
... | |||
</pre></div> | |||
a nie, matematycznie równoważnego, wyrażenia | |||
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>if ( f(x)*f(lewy) < 0 ) | |||
... | |||
</pre></div> | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> | |||
<div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Nie daj się zwieść, nie chodzi tu o zaoszczędzenie jednego mnożenia... </div> | |||
</div></div> | |||
</div></div> | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> | |||
Gdy zbliżamy się do miejsca zerowego <math>\displaystyle f</math>, wartości \lstC!f(x)! i \lstC!f(lewy)! mogą być na tyle małe, że ich iloczyn --- poprzez niedomiar --- będzie miał numeryczną wartość zero i w efekcie program może przeskoczyć do niewłaściwej gałęzi pętli <code>if</code>, a tym samym --- wybrać niewłaściwą lokalizację przedziału zawierającego poszukiwany pierwiastek. | |||
</div></div></div> | </div></div></div> |
Wersja z 20:55, 29 wrz 2006
Własności arytmetyki zmiennoprzecinkowej
<<< Powrót do strony głównej przedmiotu Metody numeryczne
Ogl�daj wskaz�wki i rozwi�zania __SHOWALL__
Ukryj wskaz�wki i rozwi�zania __HIDEALL__
Ćwiczenie: Równe i równiejsze
Wyjaśnij, dlaczego w arytmetyce podwójnej precyzji IEEE 754 mamy
Oczywiście, "teoretycznie" wszystkie trzy liczby powinny być sobie równe (i niezerowe).
Ćwiczenie: Szeregi zbieżne(?)
Podaj przykłady zbieżnych szeregów postaci , których -te sumy częściowe obliczone w arytmetyce pojedynczej precyzji algorytmem
suma = 0.0; for n = 1..N suma += <math>\displaystyle a_n</math>;
będą
- ograniczone niezależnie od , albo
- numerycznie rozbieżne, to znaczy takie, że dla bardzo dużych zachodzi
suma == Inf
.
Wykonaj to samo zadanie, ale podając przykłady szeregów rozbieżnych (w arytmetyce dokładnej).
Ćwiczenie
Dla kolejnych , wyznacz -tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy :
korzystając z algorytmu podanego w poprzednim zadaniu. Oblicz błąd względny
i bezwzględny wyznaczonego przybliżenia, w porównaniu
do wartości wyznaczonej z wykorzystaniem funkcji bibliotecznej exp()
. Powtórz następnie dla .
Czy --- zgodnie z teorią matematyczną --- sumy te dążą do wartości . Objaśnij dokładnie, co się stało.
Ćwiczenie
Już wcześniej stwierdziliśmy, że wyznaczanie dla dużego nie jest dobrym pomysłem. Przeprowadź eksperyment numeryczny potwierdzający to stwierdzenie i objaśnij jego wyniki.
Ćwiczenie
Jak wiadomo, szereg harmoniczny jest rozbieżny. Spróbuj przewidzieć, jaki będzie efekt numerycznego wyznaczenia tej sumy w arytmetyce podwójnej precyzji przy użyciu poniższego kodu.
int dlicznik; double dsuma, dstarasuma; double dskladnik; dstarasuma = 0.0; dsuma = 1.0; dlicznik = 1; while(dstarasuma != dsuma) { dskladnik = 1.0/dlicznik; dstarasuma = dsuma; dsuma += dskladnik; dlicznik++; } printf("Suma = %e. Liczba składników = %d, składnik = %e\n", dsuma, dlicznik-1, dskladnik);
Ćwiczenie: Zadanie o wyznaczaniu odwrotności bez dzielenia metodą Newtona
Należy wyznaczyć przybliżenie stosując metodę Newtona do równania
. Zaproponuj
dobre przybliżenie początkowe wiedząc, że jest liczbą maszynową typu
double
. Ile iteracji wystarczy, by osiągnąć -zadowalające przybliżenie?
Ćwiczenie
Niech . Czy z punktu widzenia błędów w lepiej jest policzyć sumę tych liczb w kolejności od najmniejszej do największej, czy odwrotnie?
Ćwiczenie
Dlaczego w algorytmie bisekcji rozwiązywania równania , sprawdzając warunek różnych znaków w krańcach przedziału , używamy kryterium
if ( sign(f(x)) != sign(f(xl)) ) ...
a nie, matematycznie równoważnego, wyrażenia
if ( f(x)*f(lewy) < 0 ) ...