MN03LAB: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Przykry (dyskusja | edycje)
mNie podano opisu zmian
m Zastępowanie tekstu – „,↵</math>” na „</math>,”
 
(Nie pokazano 47 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
''Uwaga: przekonwertowane latex2mediawiki; prawdopodobnie trzeba wprowadzi? poprawki''
<!--
Konwertowane  z pliku LaTeX przez latex2mediawiki, zob. http://www.ii.uj.edu.pl/&nbsp;pawlik1/latex2mediawiki.php.
Niezb�dne rozszerzenia i modyfikacje oryginalnego latex2mediawiki  
wprowadzi� przykry@mimuw.edu.pl
-->
=Własności arytmetyki zmiennoprzecinkowej=


{Ćwiczenia: równania nieliniowe skalarne}
{{powrot |Metody numeryczne | do strony głównej
przedmiotu <strong>Metody numeryczne</strong>}}


{{cwiczenie|Metoda Newtona może być zbieżna globalnie||
<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>


Wykaż, że jeśli <math>\displaystyle f</math> jest rosnąca i wypukła na <math>\displaystyle [a,b]</math> oraz dla <math>\displaystyle x^*\in [a,b]\displaystyle f(x^*) = 0</math>, to metoda Newtona startująca z <math>\displaystyle x_0>x^*</math> jest zbieżna.
<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: Równe i równiejsze</span>  
<div class="exercise">
 
Wyjaśnij, dlaczego w arytmetyce podwójnej precyzji IEEE 754 mamy
<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
ans = 0
octave:20> 2.006/1e306
ans =  2.0060e-306
octave:21> (2006/1000)/(1e309/1000)
ans = 0
</nowiki></div>
Oczywiście, "teoretycznie" wszystkie trzy liczby powinny być sobie
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 style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Kluczem jest wyjaśnienie, jaka jest reprezentacja liczby <math>10^{309}</math> w podwójnej precyzji... A reprezentacja <math>10^{306}</math>? </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"> 
Powtarzając rachunki z dowodu lokalnej zbieżności, możemy łatwo stwierdzić, że kolejne
iteracje dają <math>\displaystyle x_k</math> które także spełniają warunek <math>\displaystyle x_k - x^* > 0</math>. Ponadto
nietrudno sprawdzić, że <math>\displaystyle x_{k+1} < x_k</math>, a więc mamy ciąg malejący i
ograniczony. Jego granicą musi być <math>\displaystyle x^*</math> (dlaczego?).
</div></div>
</div></div>


{{cwiczenie|Fraktale||
<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: Szeregi zbieżne(?)</span>
<div class="exercise">


Ciekawy zbiór o charakterze fraktalnym powstaje w wyniku zastosowania metody
Podaj przykłady <strong>zbieżnych</strong> szeregów postaci <math>\sum_{n=1}^{\infty} a_n</math>, których <math>N</math>-te sumy częściowe
Newtona do rozwiązania równania <math>\displaystyle z^n-1=0</math> w dziedzinie zespolonej. Punkt <math>\displaystyle z_0 =
obliczone w arytmetyce pojedynczej precyzji algorytmem
(x_0,y_0)</math> należy do ''basenu zbiezności metody'', jeśli metoda Newtona jest
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>suma = 0.0;
zeń zbieżna do (jakiegokolwiek) pierwiastka w/w równania. Kolor odpowiadający
for n = 1..N
<math>\displaystyle z_0</math> jest określany na podstawie liczby iteracji potrzebnych metodzie do
suma += <math>a_n</math>;
zbieżności.
</pre></div>
będą
* ograniczone niezależnie od <math>N</math>, albo
* numerycznie rozbieżne, to znaczy takie, że dla bardzo dużych <math>N</math> zachodzi <code style="color: #006">suma == Inf</code>.
Wykonaj to samo zadanie, ale podając przykłady szeregów  <strong>rozbieżnych</strong> (w
arytmetyce dokładnej).
</div></div>


Zupełnie miłym (i estetycznie wartościowym) doświadczeniem, jest napisanie
<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"> 
programu w Octave, który wyświetla baseny zbieżności metody Newtona jak poniżej.


[[Image:fraktal.png|thumb|right|400px|Basen zbiezności metody Newtona w okolicy początku układu
Rozpatrz na przykład takie szeregi:
współrzędnych, dla równania <math>\displaystyle z^5-1=0</math>]]
* Szereg zerowy (numerycznie dostajesz oczywiście też 0)
* <math>1 + 10^{2006} - 10^{2006} + 0 + \ldots = 1</math> oraz <math>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ąć).
* Szereg jedynkowy.
</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">Wskazówka </span><div class="mw-collapsible-content" style="display:none">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
Bardzo wygodnie napisać taki program w postaci skryptu Octave. Pamiętaj
<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>  
jednak, by uniknąć w nim pętli w rodzaju
<div class="exercise">


for xpixels <nowiki>=</nowiki> 1:1024<br>
Dla kolejnych <math>N</math>, wyznacz <math>N</math>-tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy <math>x=-90</math>:
for ypixels <nowiki>=</nowiki> 1:768<br>
<center><math>
... wyznacz kolor pixela ....<br>
e^x \approx \sum_{n=0}^N \frac{x^n}{n!}</math>,</center>
end<br>
end<br>


Taka podwójnie zagnieżdżona pętla może skutecznie zniechęcić Cię do
korzystając z algorytmu podanego w poprzednim zadaniu. Oblicz błąd względny
Octave'a --- obrazek będzie liczyć się wieki --- zupełnie niepotrzebnie!
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>x=10</math>.


Czy --- zgodnie z teorią matematyczną --- sumy te dążą do wartości
<math>e^{x}</math>. Objaśnij dokładnie, co się stało.
</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">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">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> 
Kluczem do efektywnej implementacji w Octave jest przeprowadzenie
Zastosowanie naszego algorytmu dla <math>x=-90</math> daje w wyniku (dla arytmetyki
iteracji Newtona na ''wszystkich pikselach jednocześnie''. W tym celu musisz
podwójnej precyzji) sumę równą około <math>10^{30}</math>,
skorzystać z prowadzenia działań na całych macierzach.
gdy oczywiście naprawdę <math>\exp(-90)
</div></div>
\approx 0</math>). Problem jest skutkiem zjawiska redukcji cyfr przy odejmowaniu: aby
nasza suma była równa zeru, w pewnym momencie musimy odjąć duży składnik od
innego podobnego, by w rezultacie dostać coś małego. Spróbuj wychwycić ten
moment i wartość dodawanego składnika.
 
Dla <math>x=10</math> mamy, dla rosnącego <math>N</math>, całkiem niezły błąd względny ostatecznego
wyniku.


}}
</div></div></div>


{{cwiczenie|Pierwiastkowanie||
<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">


Niech <math>\displaystyle a\geq 0</math>. Aby wyznaczyć <math>\displaystyle \sqrt{a}</math>, można skorzystać z metody Newtona dla
Już wcześniej stwierdziliśmy, że wyznaczanie <math>e \approx (1 + 1/n)^n</math> dla dużego
równania <math>\displaystyle x^2 = a</math>. Zaprogramuj tę metodę i sprawdź, jak wiele dokładnych cyfr
<math>n</math> nie jest dobrym pomysłem. Przeprowadź eksperyment numeryczny potwierdzający
wyniku dostajesz w kolejnych krokach. Czy to możliwe, by liczba dokładnych cyfr
to stwierdzenie i objaśnij jego wyniki.  
znaczących z grubsza podwajała się na każdej iteracji? Wskaż takie <math>\displaystyle a</math> dla
którego to nie będzie prawdą.


<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">
Na pewno kusi Cię, by zaprogramować najpierw ogólnie funkcję "metoda
<div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Kiedy da znać o sobie epsilon maszynowy? </div>
Newtona", a następnie przekazać jej jako parametr naszą funkcję. To oczywiście
będzie działać, i to praktycznie tak samo szybko jak drugi spsoób, w którym po prostu
wyliczysz na karteczce wzór na iterację dla ''tej konkretnej funkcji, <math>\displaystyle F(x) =
x^2-a</math>'' i potem go zaimplementujesz. Jednak
drugie podejście jest tutaj godne polecenia, bo ma na sobie znak charakterystyczny dla numeryki: niech
wszystko, co programujesz będzie tak proste, jak tylko możliwe (ale nie
prostsze)!
</div></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-top:1em; padding-top,padding-bottom:1em;">
Nasza iteracja, którą chcemy zaprogramować, to
<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>  
<center><math>\displaystyle
<div class="exercise">
x_{k+1} = \frac{1}{2}\left( x_k + \frac{a}{x_k}\right).
</math></center>


Dla <math>\displaystyle a\neq 0</math>, spełnione są założenia twierdzenia o zbieżności metody Newtona,
Jak wiadomo, szereg harmoniczny <math>\sum_{n=1}^\infty 1/n</math> jest rozbieżny.
więc
Spróbuj przewidzieć, jaki będzie efekt numerycznego wyznaczenia tej sumy w
arytmetyce podwójnej precyzji przy użyciu poniższego kodu.


<center><math>\displaystyle |x_{k+1}-x^*|\leq K |x_{k}-x^*|^2
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>int dlicznik;
</math></center>
double dsuma, dstarasuma;
 
double dskladnik;
co właśnie tłumaczy się jako podwajanie liczby dokładnych cyfr
znaczących wyniku.
dstarasuma = 0.0; dsuma = 1.0; dlicznik = 1;
 
while(dstarasuma != dsuma)
Ale jeśli <math>\displaystyle a=0</math> to metoda zbieżna jest już tylko liniowo (z ilorazem 0.5 --- bo
{
jaki wtedy jest wzór na iterację?), więc co mniej więcej trzy kroki będziemy
dskladnik = 1.0/dlicznik;
dostawali kolejne zero dokładnego wyniku <math>\displaystyle x^*=0</math>.
dstarasuma = dsuma;
dsuma += dskladnik;
dlicznik++;
}
printf("Suma = &#37;e. Liczba składników = &#37;d, składnik = &#37;e\n",
dsuma, dlicznik-1, dskladnik);
</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"> Policz, ile mniej więcej obrotów pętli potrzeba, by suma przestała rosnąć. </div>
</div></div>


</div></div>
</div></div>


{{cwiczenie|Odwrotność bez dzielenia||
<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
być dskładnik <math>\approx 10^{-15}</math> (lub więcej). Tymczasem zakres liczb typu integer wynosi niewiele ponad <math>10^9</math>, więc po jakimś czasie <code>dlicznik</code> przyjmie wartości ujemne.


Aby wyznaczyć <math>\displaystyle 1/a</math> dla <math>\displaystyle a>0</math> bez dzielenia(!), można zastosować metodę Newtona
</div></div></div>
do funkcji <math>\displaystyle f(x) = 1/x - a</math>. Pokaż, że na <math>\displaystyle k</math>-tym kroku iteracji,
<center><math>\displaystyle
|ax_k - 1| = |ax_{k-1} - 1|^2.
</math></center>


Dla jakich <math>\displaystyle x_0</math> metoda będzie zbieżna do <math>\displaystyle \frac{1}{a}</math>, a dla jakich nie?
<!--  
Oceń, ile iteracji potrzeba do spełnienia warunku <math>\displaystyle \frac{|x_k-\frac{1}{a}|}{|a|} \leq
\epsilon</math>, gdy <math>\displaystyle \frac{|x_0-\frac{1}{a}|}{|a|} \leq \gamma < 1</math>,
}}


<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-top:1em; padding-top,padding-bottom:1em;">
Proste ćwiczenie z analizy. Warunkiem zbieżności jest oczywiście (ze względu na
<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 pierwiastka kwadratowego metodą Newtona</span>  
równość w wyrażeniu na błąd iteracji powyżej) <math>\displaystyle |ax_0 - 1| < 1</math>, to znaczy
<div class="exercise">
<center><math>\displaystyle 0 < x_0 < \frac{2}{a}.</math></center>


Dla zadanej liczby <math>a>1</math> należy wyznaczyć przybliżenie <math>\sqrt{a}</math> stosując metodę Herona. Zaproponuj
dobre przybliżenie początkowe <math>x_0</math> wiedząc, że <math>a</math> jest liczbą maszynową typu
<code>double</code>. Ile iteracji wystarczy, by osiągnąć <math>\epsilon</math>-zadowalające przybliżenie?
</div></div>
</div></div>


{{cwiczenie|||
<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">
Zaimplementuj metodę bisekcji. Sprawdź, jak będzie działać m.in. dla funkcji
 
# <math>\displaystyle f(x) = \sin(x)</math>,
Jak pamiętamy, <math>a = (1+f)2^p = \widetilde{f} 2^{p+1}</math>,
# <math>\displaystyle f(x) = \sin^2(x)</math>,
gdzie <math>\frac{1}{2}\leq \widetilde{f} < 1</math> oraz <math>p\in N</math>. Stąd
# <math>\displaystyle f(x) = (x-1)^5</math> (wzór A),
# <math>\displaystyle f(x) = (x-1)*(x^4 - 4x^3 + 6x^2 - 4x + 1)</math> (wzór B),
# <math>\displaystyle f(x) = (x-2)^13</math> (wzór C),
# <math>\displaystyle f(x) = x^13 - 26*x^12 + 312*x^11 - 2288*x^10 + ... - 8192</math> (wzór D),


gdy tolerancję błędu zadasz na poziomie <math>\displaystyle 10^{-10}</math>.
<center><math>
\sqrt{a} = \sqrt{\widetilde{f}}2^{(p+1)/2} = \sqrt{g} 2^k</math>,</center>


Jak wyjaśnić te wyniki? Czy możesz już być pewna, że masz dobrą implementację?
dla pewnego (znanego) <math>k \in N</math>, przy czym <math>\frac{1}{2} \leq \sqrt{g} \leq 1</math>.
Wobec tego, obliczenie
<math>\sqrt{a}</math> wymaga po prostu wyznaczenia <math>\sqrt{g}</math>. Najprostsze przybliżenie <math>\sqrt{g}</math> to
<math>\sqrt{g}\approx 1</math>. Błąd takiego przybliżenia to
<math>|\sqrt{g} - 1| \leq 0.5</math>.


}}
Jak można jeszcze bardziej poprawić <math>x_0</math>?


<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></div></div>


Jeśli nie pomylisz się, metoda powinna zbiegać bez problemów do zera funkcji
-->
<math>\displaystyle \sin</math>, dawać komunikat o błędzie dla <math>\displaystyle \sin^2</math> (bo nie ma przeciwnych znaków).
<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>  
<div class="exercise">


Zapewne zauważyłaś, że wzory A i B są matematycznie równoważne, podobnie zresztą
Należy wyznaczyć przybliżenie <math>\frac{1}{a}</math> stosując metodę Newtona do równania
jak wzory C i D. Niestety, tylko wzór A i C dają w efekcie dobre przybliżenia
<math>\frac{1}{x} - a = 0</math>. Zaproponuj
miejsca zerowego, podczas gdy wzory B i D prowadzą do oszacowania na miejsce
dobre przybliżenie początkowe <math>x_0</math> wiedząc, że <math>a</math> jest liczbą maszynową typu
zerowe, które ''w ogóle nie zawierają'' prawdziwego miejsca zerowego.
<code>double</code>. Ile iteracji wystarczy, by osiągnąć <math>\epsilon</math>-zadowalające przybliżenie?
</div></div>


Wyjaśnieniem tego fenomenu jest zjawisko redukcji cyfr przy odejmowaniu.
<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"> 
Jak pamiętamy, <math>a = (1+f)2^p</math>, skąd <math>\frac{1}{a} = \frac{1}{1+f}2^{-p}</math>.
Wystarczy więc przybliżyć <math>\frac{1}{1+f}</math>. Ponieważ dla <math>0 \leq f < 1</math>,


[[Image:bisekcjawblad.png|thumb|right|400px|Metoda bisekcji ma kłopoty, gdy funkcja zadana jest
<center><math>\frac{1}{2} \leq \frac{1}{1+f} \leq 1</math>,</center>
wzorem D.]]
[[Image:bisekcjawresid.png|thumb|right|400px|Residuum też jest duże, gdy <math>\displaystyle f</math> zadana jest
wzorem D.]]


Jeśli chodzi o pewność... No cóż, sprawdziłaś, że działa w przypadkach, gdy
to możemy jako pierwsze przybliżenie wybrać <math>x_0 = \frac{3}{4}2^{-p}</math> (jak
spodziewałaś się, że będzie działać. Że tam, gdzie spodziewałaś się kłopotów,
wybrać jeszcze lepsze <math>x_0</math>?)
lub komunikatu o błędzie --- tak rzeczywiście się stało. Wreszcie,
potwierdziłaś, że zachowanie metody jest zgodne z jej znanymi właściwościami.


Tak więc, można ''przypuszczać'', że implementacja jest poprawna.
Wtedy mamy następujące oszacowania:


</div></div>
<center><math>|x_0a - 1| = |\frac{3}{4}2^{-p}\cdot (1+f)2^p - 1| = |\frac{3}{4}(1+f) - 1|
\leq \frac{1}{2}</math></center>


{{cwiczenie|||
Ponieważ iteracja Newtona spełnia
Wskaż ''wszystkie'' wartości <math>\displaystyle x_0</math>, dla jakich metoda Newtona będzie zbieżna
do rozwiązania <math>\displaystyle x^*</math> równania


<center><math>\displaystyle \arctan(x) = 0.
<center><math>|x_{k+1}a - 1| = |x_ka-1|^2 = |x_0a-1|^{2^k}</math>,</center>
</math></center>


Wyznacz wartość <math>\displaystyle X_0</math>, z którego startując powinieneś dostać ciąg oscylujący <math>\displaystyle X_0, -X_0,\ldots</math>.
to, jeśli chcemy, by błąd względny przybliżenia <math>x_{k+1}</math> spełniał <math>\frac{|x_{k+1} -
Sprawdź eksperymentalnie, czy tak jest rzeczywiście.
\frac{1}{a}|}{\frac{1}{a}} = |x_{k+1}a - 1| \leq \epsilon = 2^{-53}</math>,  
musimy wykonać co najwyżej <math>6</math> iteracji. Ponieważ koszt jednej iteracji
to 3 działania arytmetyczne,  wyznaczenie odwrotności <math>a</math> byłoby 18 razy droższe od mnożenia i dodawania, które mają podobny koszt.


<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">
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].
Aby znaleźć graniczne <math>\displaystyle X_0</math>, czyli takie, dla którego dostaniesz
oscylacje <math>\displaystyle X_0, -X_0,\ldots</math>, musisz rozwiązać równanie nieliniowe:


<center><math>\displaystyle -X_0 = X_0 - \frac{\arctan(X_0)}{\frac{1}{1+X_0^2}}.
Więcej na temat implementacji algorytmów dzielenia oraz wyciągania pierwiastka
</math></center>
kwadratowego możesz dowiedzieć się np. z artykułu Petera Marksteina
[http://www.informatik.uni-trier.de/Reports/TR-08-2004/rnc6_12_markstein.pdf  Software Division and Square Root Using Goldschmidt s Algorithms] oraz
[http://arith.stanford.edu/techrep.html  raportów technicznych Stanford Computer Architecture and Arithmetic Group]
</div></div></div>


To łatwe.
<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">


Niech <math>0 < a_1 < a_2 < \cdots < a_n</math>. Czy z punktu widzenia
błędów w <math>fl_\nu</math> lepiej jest policzyć sumę tych liczb w kolejności
od najmniejszej do największej, czy odwrotnie?
</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"> 
Od najmniejszej do największej.
</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-top:1em; padding-top,padding-bottom:1em;">
Dla <math>\displaystyle -X_0 < x_0 < X_0</math> mamy zbieżność. Dla <math>\displaystyle |x_0| = |X_0|</math> oscylacje, dla
<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>  
większych wartości --- rozbieżność. Jednak w eksperymencie wszystko zależy od
<div class="exercise">
tego, jak dokładnie wyznaczyliśmy <math>\displaystyle X_0</math>. Na przykład, mój solver w Octave
wyznaczył wartość <math>\displaystyle X_0</math>, dla której metoda Newtona dała następujący ciąg:


Iteracja:  1,   x <nowiki>=</nowiki> -1.39175
Dlaczego w algorytmie bisekcji rozwiązywania równania <math>f(x)=0</math>, sprawdzając warunek różnych znaków <math>f</math> w krańcach przedziału <math>[a,b]</math>, używamy kryterium
Iteracja:  2,  x <nowiki>=</nowiki> 1.39175
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>if ( sign(f(x)) != sign(f(xl)) )
Iteracja:   3,  x <nowiki>=</nowiki> -1.39175
...
Iteracja:  4,  x <nowiki>=</nowiki> 1.39175
</pre></div>
Iteracja:   5,   x <nowiki>=</nowiki> -1.39175
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>


.. itd ..
</div></div>


Iteracja:  25,  x <nowiki>=</nowiki> -1.39176
<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">  
Iteracja:  26,  x <nowiki>=</nowiki> 1.39178
Gdy zbliżamy się do miejsca zerowego <math>f</math>, wartości <code>f(x)</code> i <code>f(lewy)</code> 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.
Iteracja:  27,  x <nowiki>=</nowiki> -1.39183
</div></div></div>
Iteracja:  28,  x <nowiki>=</nowiki> 1.39197
Iteracja: 29,  x <nowiki>=</nowiki> -1.39235
Iteracja:  30,  x <nowiki>=</nowiki> 1.39333
Iteracja:  31,  x <nowiki>=</nowiki> -1.39594
Iteracja: 32,  x <nowiki>=</nowiki> 1.40283
Iteracja:  33,  x <nowiki>=</nowiki> -1.42117
Iteracja34,  x <nowiki>=</nowiki> 1.47061
Iteracja:  35,  x <nowiki>=</nowiki> -1.60867
Iteracja:  36,   x <nowiki>=</nowiki> 2.03161
Iteracja:  37,  x <nowiki>=</nowiki> -3.67722
Iteracja:  38,  x <nowiki>=</nowiki> 15.2779
Iteracja:  39,   x <nowiki>=</nowiki> -337.619
Iteracja:  40,  x <nowiki>=</nowiki> 178376
Iteracja:  41,   x <nowiki>=</nowiki> -4.99792e+10
Iteracja:  42,  x <nowiki>=</nowiki> 3.92372e+21
Iteracja:  43,  x <nowiki>=</nowiki> -2.41834e+43
Iteracja:  44,  x <nowiki>=</nowiki> 9.18658e+86
Iteracja:  45,  x <nowiki>=</nowiki> -1.32565e+174
Iteracja:  46,  x <nowiki>=</nowiki> inf
Iteracja:  47,  x <nowiki>=</nowiki> nan
 
</div></div>

Aktualna wersja na dzień 21:44, 11 wrz 2023


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

octave:19> 2006/1e309 ans = 0 octave:20> 2.006/1e306 ans = 2.0060e-306 octave:21> (2006/1000)/(1e309/1000) ans = 0

Oczywiście, "teoretycznie" wszystkie trzy liczby powinny być sobie równe (i niezerowe).

Wskazówka

Ćwiczenie: Szeregi zbieżne(?)

Podaj przykłady zbieżnych szeregów postaci n=1an, których N-te sumy częściowe obliczone w arytmetyce pojedynczej precyzji algorytmem

suma = 0.0;
for n = 1..N
	suma += <math>a_n</math>;

będą

  • ograniczone niezależnie od N, albo
  • numerycznie rozbieżne, to znaczy takie, że dla bardzo dużych N zachodzi suma == Inf.

Wykonaj to samo zadanie, ale podając przykłady szeregów rozbieżnych (w arytmetyce dokładnej).

Rozwiązanie

Ćwiczenie

Dla kolejnych N, wyznacz N-tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy x=90:

exn=0Nxnn!,

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 x=10.

Czy --- zgodnie z teorią matematyczną --- sumy te dążą do wartości ex. Objaśnij dokładnie, co się stało.

Rozwiązanie

Ćwiczenie

Już wcześniej stwierdziliśmy, że wyznaczanie e(1+1/n)n dla dużego n nie jest dobrym pomysłem. Przeprowadź eksperyment numeryczny potwierdzający to stwierdzenie i objaśnij jego wyniki.

Wskazówka

Ćwiczenie

Jak wiadomo, szereg harmoniczny n=11/n 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);
	 
Wskazówka
Rozwiązanie


Ćwiczenie: Zadanie o wyznaczaniu odwrotności bez dzielenia metodą Newtona

Należy wyznaczyć przybliżenie 1a stosując metodę Newtona do równania 1xa=0. Zaproponuj dobre przybliżenie początkowe x0 wiedząc, że a jest liczbą maszynową typu double. Ile iteracji wystarczy, by osiągnąć ϵ-zadowalające przybliżenie?

Rozwiązanie

Ćwiczenie

Niech 0<a1<a2<<an. Czy z punktu widzenia błędów w flν lepiej jest policzyć sumę tych liczb w kolejności od najmniejszej do największej, czy odwrotnie?

Rozwiązanie

Ćwiczenie

Dlaczego w algorytmie bisekcji rozwiązywania równania f(x)=0, sprawdzając warunek różnych znaków f w krańcach przedziału [a,b], używamy kryterium

if ( sign(f(x)) != sign(f(xl)) )
...	

a nie, matematycznie równoważnego, wyrażenia

if ( f(x)*f(lewy) < 0 )	
...
Wskazówka
Rozwiązanie