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
Kluczem jest wyjaśnienie, jaka jest reprezentacja liczby w podwójnej precyzji... A reprezentacja ?
Ć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).
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ąć).
- Szereg jedynkowy.
Ć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.
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.
Wskazówka
Kiedy da znać o sobie epsilon maszynowy?
Ć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.
Ć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ć jeszcze 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ł ,
musimy wykonać co najwyżej iteracji. Ponieważ koszt jednej iteracji
to 3 działania arytmetyczne, 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.
Ć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 )
...
Wskazówka
Nie daj się zwieść, nie chodzi tu o zaoszczędzenie jednego mnożenia...
Rozwiązanie
Gdy zbliżamy się do miejsca zerowego , wartości f(x)
i 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 if
, a tym samym --- wybrać niewłaściwą lokalizację przedziału zawierającego poszukiwany pierwiastek.