|
|
Linia 248: |
Linia 248: |
| <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">
| |
|
| |
| Aby obliczyć <math>\displaystyle S(a,b)=a^2-b^2</math> można zastosować
| |
| dwa algorytmy: <math>\displaystyle {\bf ALG}_1(a,b)=a*a-b*b</math> oraz <math>\displaystyle {\bf ALG}_2(a,b)=(a+b)*(a-b)</math>.
| |
| Pokazać, że oba algorytmy są numerycznie poprawne, ale drugi
| |
| z nich wywołuje mniejszy błąd względny wyniku w przypadku, gdy
| |
| <math>\displaystyle rd_\nu(a)=a</math> i <math>\displaystyle rd_\nu(b)=b</math>.
| |
| </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">
| |
|
| |
| Pokazać, że naturalny algorytm obliczania cosinusa
| |
| kąta między dwoma wektorami <math>\displaystyle a, b\inR^n</math>,
| |
|
| |
| <center><math>\displaystyle \cos(a,b)\,=\,\frac{\sum_{j=1}^n a_jb_j}
| |
| {\sqrt{\Big(\sum_{j=1}^n a_j^2\Big)
| |
| \Big(\sum_{j=1}^n b_j^2\Big)}},
| |
| </math></center>
| |
|
| |
| jest numerycznie poprawny. Oszacować błąd względny wyniku
| |
| w <math>\displaystyle fl_\nu</math>.
| |
| </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">
| |
|
| |
| Pokazać, że naturalny algorytm obliczania
| |
| <math>\displaystyle \|A x\|_2</math> dla danej macierzy <math>\displaystyle A\inR^{n\times n}</math> i wektora
| |
| <math>\displaystyle x\inR^n</math> jest numerycznie poprawny. Dokładniej,
| |
|
| |
| <center><math>\displaystyle fl_\nu (\|A x\|_2)\,=\,(A+E) x,
| |
| </math></center>
| |
|
| |
| gdzie <math>\displaystyle \|E\|_2\leq 2(n+2)\sqrt n\nu\|A\|_2</math>. Ponadto, jeśli
| |
| <math>\displaystyle A</math> jest nieosobliwa to
| |
|
| |
| <center><math>\displaystyle |fl_\nu(\|A x\|_2)-\|A x\|_2|\,\leq\,2(n+2)\sqrt{n}\,\nu\,
| |
| \left(\|A\|_2\|A^{-1}\|_2\right)\,\|A x\|_2.
| |
| </math></center>
| |
|
| |
| </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">
| |
|
| |
| Niech <math>\displaystyle {\bf ALG}</math> będzie algorytmem numerycznie
| |
| poprawnym w zbiorze danych <math>\displaystyle f\in F_0</math>, przy czym dla małych <math>\displaystyle \nu</math>,
| |
| <math>\displaystyle fl_\nu({\bf ALG}(f))=\varphi(y_\nu)</math>, gdzie <math>\displaystyle \|y_\nu-y\|\le K\nu\|y\|</math>
| |
| i <math>\displaystyle K</math> nie zależy od <math>\displaystyle \nu</math> i <math>\displaystyle f</math> (<math>\displaystyle y=N(f)</math>). Pokazać, że
| |
| w ogólności <math>\displaystyle {\bf ALG}</math> nie musi być "numerycznie poprawny po
| |
| współrzędnych", tzn. w ogólności nie istnieje bezwzględna
| |
| stała <math>\displaystyle K_1</math> taka, że dla małych <math>\displaystyle \nu</math> i dla dowolnej
| |
| <math>\displaystyle f\in F_0</math>
| |
|
| |
| <center><math>\displaystyle |y_{\nu,j}-y_j|\,\le\,K_1\,\nu\,|y_j|, \qquad 1\le j\le n,
| |
| </math></center>
| |
|
| |
| gdzie <math>\displaystyle y=(y_1,\ldots,y_n)</math>.
| |
| </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">
| |
|
| |
| Podaj przykład funkcji <math>\displaystyle f</math>, której miejsce zerowe <math>\displaystyle x^*</math> ma wspólczynnik
| |
| uwarunkowania
| |
| * mały
| |
| * duży
| |
|
| |
| </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">
| |
| Ponieważ nasze zadanie to wyznaczenie <math>\displaystyle x^* = f^{-1}(0)</math>, to
| |
| <center><math>\displaystyle
| |
| \mbox{cond} _{abs} (f^{-1},0) = \frac{1}{f'(x^*)}.
| |
| </math></center>
| |
|
| |
| Znaczy to, że im bardziej płaska jest <math>\displaystyle f</math> w otoczeniu pierwiastka <math>\displaystyle x^*</math>, tym
| |
| bardziej nawet małe zaburzenia <math>\displaystyle f</math> mogą spowodować duże przemieszczenie jej
| |
| miejsca zerowego.
| |
|
| |
| Zauważ, że dla wielokrotnych miejsc zerowych, <math>\displaystyle \mbox{cond} _{abs} (f^{-1},0) = \infty</math>,
| |
| co zgadza się z intuicją, bo może być, że nawet minimalne zaburzenie <math>\displaystyle f</math>
| |
| spowoduje, iż miejsc zerowych po prostu nie będzie...
| |
| </div></div></div> | | </div></div></div> |
Ćwiczenia. Własności arytmetyki zmiennopozycyjnej.
Ć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
Kluczem jest stwierdzenie, jaka jest reprezentacja liczby w podwójnej precyzji? A
?
Ćwiczenie: Szeregi zbieżne(?)
Podaj przykłady zbieżnych szeregów postaci , którego -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).
Rozwiązanie
Rozpatrz na przykład takie szeregi:
- Szereg zerowy (numerycznie dostajesz oczywiście też 0)
- oraz
(numerycznie dostaniesz, odpowiednio, NaN
(dlaczego?) i Inf
.
- Szereg harmoniczny (numerycznie sumy częściowe w pewnym momencie przestaną
rosnąć).
Ćwiczenie
Dla kolejnych , wyznacz -tą sumę częściową szeregu Taylora dla funkcji wykładniczej, gdy :
korzystając z algorytmu podanego w poprzednim zadaniu. Porównaj błąd: względny
i bezwzględny 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.
Rozwiązanie
Zastosowanie naszego algorytmu dla daje w wyniku (dla arytmetyki
podwójnej precyzji) sumę równą około ,
gdy oczywiście naprawdę ). 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 mamy, dla rosnącego , całkiem niezły błąd względny ostatecznego
wyniku.
Ć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);
Wskazówka
Policz, ile mniej więcej obrotów pętli potrzeba, by suma przestała rosnąć.
Rozwiązanie
Nasza suma przekroczy wartość 20, więc aby 20 + dskladnik == 20
, musi
być dskładnik (lub więcej). Tymczasem zakres liczb typu integer wynosi
niewiele ponad , więc po jakimś czasie dlicznik przyjmie wartości ujemne.
Aby doliczyć się "do końca", musielibyśmy licznik potraktować jako liczbę typu
long long double
, którego zakres sięga . Ale i tak mielibyśmy
kłopot z doczekaniem do końca działalności programu.
Zakładając optymistycznie, że na sekundę zliczamy składników,
potrzebowalibyśmy razem około sekund, czyli ponad trzy miesiące...
Ćwiczenie
Jak szybko i na jakiej wysokości musiałby lecieć samolot npla, aby
pocisk wystrzeliwany z działka z prędkością 7500 km/h nie trafił w cel, gdy
potrzebne pierwiastki liczone są wzorem szkolnym?
Ćwiczenie: Zadanie o wyznaczaniu pierwiastka kwadratowego metodą Newtona
Dla zadanej liczby , należy wyznaczyć przybliżenie stosując metodę Herona. Zaproponuj
dobre przybliżenie początkowe wiedząc, że jest liczbą maszynową typu
double
. Ile iteracji wystarczy, by osiągnąć -zadowalające przybliżenie?
Rozwiązanie
Jak pamiętamy, ,
gdzie oraz . Stąd
dla pewnego (znanego) , przy czym .
Wobec tego, obliczenie
wymaga po prostu obliczenia . Najprostsze przybliżenie to
. Błąd takiego przybliżenia to
.
Jak można jeszcze bardziej poprawić ?
Ć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?
Rozwiązanie
Jak pamiętamy, , skąd .
Wystarczy więc przybliżyć . Ponieważ dla ,
to możemy jako pierwsze przybliżenie wybrać . (Jak
wybrać lepsze ?)
Wtedy mamy następujące oszacowania:
Ponieważ iteracja Newtona spełnia
to, jeśli chcemy, by błąd względny przybliżenia spełniał , to
musimy wykonać co najwyżej iteracji. Ponieważ koszt jednej iteracji
to 3 flopy, zatem wyznaczenie odwrotności byłoby 18 razy droższe od
mnożenia i dodawania, które mają podobny koszt.
Tymczasem, we współczesnych realizacjach, dzielenie jest tylko około 4 razy droższe od
mnożenia! Możesz sprawdzić,
jak to się dzieje np. w procesorach AMD.
Więcej na temat implementacji algorytmów dzielenia oraz wyciągania pierwiastka
kwadratowego możesz dowiedzieć się np. z artykułu Petera Marksteina
Software Division and Square Root Using Goldschmidt s Algorithms oraz
raportów technicznych Stanford Computer Architecture and Arithmetic Group
Ć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?
Rozwiązanie
Od najmniejszej do największej.