Rozdziaª 4 Arytmetyka zmiennopozycyjna Wszystkie obliczenia w octavie s wykonywane w arytmetyce zmiennopozycyjnej (inaczej - arytmetyce ) podwójnej precyzji (double) - cho w najnowszych wersjach octave'a istnieje mo»liwo± u»ywania zmiennych typu single, czyli zmiennych w pojedynczej precyzji arytmetyki zmiennopozycyjnej. Dokªadno± wzgl dna arytmetyki podwójnej precyzji wynosi ok. 10 16, a dokªadno± arytmetyki pojedynczej precyzji wynosi ok. 10 7. W octavie jest kilka funkcji zwi zanych bezpo±rednio z wªasno±ciami arytmetyki, mianowicie: eps - zwraca epsilon maszynowy arytmetyki, tzn. najmniejsz liczb ɛ tak,»e fl(ɛ + 1) > 1. Tu fl() oznacza wynik dziaªania w arytmetyce zmiennopozycyjnej. Octave domy±lnie dziaªa na liczbach zmiennopozycyjnych w podwójnej precyzji arytmetyki wi c oczywi±cie eps zwróci nam epsilon maszynowy dla arytmetyki podwójnej precyzji. Z kolei wywoªanie eps(a) - dla a liczby zwróci odlegªo± od a do najbli»szej wi kszej od a liczby w arytmetyce zmiennopozycyjnej single (x) - funkcja konwertuj ca zmienn np. typu double, czyli w podwójnej precyzji arytmetyki, do zmiennej typu single, czyli w pojedynczej precyzji arytmetyki zmiennopozycyjnej double(x) - funkcja konwertuj ca zmienn do typu zmiennej w podwójne precyzji arytmetyki, czyli odwrotna do funkcji single (x). Podwójna precyzja jest w octavie domy±lna, wi c wydaje si»e, gªównym zastosowaniem tej funkcji jest konwersja zmiennej typu single z powrotem do typu double Zastosujmy funkcj eps - sprawd¹my, czy rzeczywi±cie eps + 1 w jest wi ksze od jeden, a np. eps/2 + 1 ju» nie - tu fragment kodu octave'a: 36
i f ( ( eps+1)>1) printf ( "%g+1>1 w f l \n", eps ) ; else printf ( "%g n i e j e s t epsilonem maszynowym\n", eps ) ; i f ((1+eps/2)==1) printf ( " f l (%g+1)=1\n", eps / 2 ) ; Rysunek 4.1: Dwa sposoby obliczania f(x) = 1 cos(x) w arytmetyce zmiennopozycyjnej. Przy pomocy eps mo»emy znale¹ najmniejsz liczb dodatni w arytmetyce podwójnej precyzji: octave :33> x=eps ( 0 ) x = 4.9407 e 324 octave :34> Sprawd¹my: 37
octave :34> x/2>0 ans = 0 octave :35> Sprawd¹my, jak dziaªaj funkcje zwi zane ze zmian precyzji arytmetyki single i double - tu fragment sesji octave'a: b=s i n g l e ( eps ) i f ( ( s i n g l e ( eps)+1)==1) printf ( " f l ( s i n g l e ( eps)+1)==1\n" ) ; i f ( ( double (b)+1)>1) printf ( " f l ( double ( s i n g l e ( eps ))+1) >1.\n" ) ; #a t e r a z e p s i l o n maszynowy p r e c y z j a pojedyncza eps ( s i n g l e ( 1 ) ) Otrzymali±my,»e epsilon maszynowy w podwójnej precyzji wynosi: 2.2204e 16, a w pojedynczej precyzji arytmetyki: 1.1921e 07. Teraz znajdziemy najmniejsz liczb dodatni w arytmetyce pojedynczej precyzji: octave :52> eps ( s i n g l e ( 0 ) ) ans = 1.4013 e 45 octave :53> 4.1 Redukcja cyfr przy odejmowaniu Inn wªasno±ci arytmetyki, która mo»e powodowa problemy, jest tzw. redukcja cyfr przy odejmowaniu liczb tego samego znaku. 4.1.1 Przykªad Przetestujmy to na dwóch równowa»nych wzorach na funkcj f(x) = cos(x) 1 = 1 2 sin 2 (0.5 x) 1 = 2 sin 2 (0.5 x). Przetestujmy oba wzory dla x bliskich zeru: f 1=@( x ) cos ( x) 1; f 2=@( x ) 2 sin ( 0. 5 x ). sin ( 0. 5 x ) ; a=1e 7; 38
x=linspace( a, a, 1 0 0 0 ) ; plot ( x, f 1 ( x ), " ; wzor 1 ; ", x, f 2 ( x ), " ; wzor 2 ; " ) ; Wykres na rysunku 4.1 pokazuje,»e wzór drugi jest lepszy ze wzgl du na arytmetyk. Mo»emy oczywi±cie policzy te» bª d pomi dzy wynikami: er=f 1 (1 e 7) f 2 (1 e 7) Ró»nica 3.9964e 18 jest pozornie maªa, bo rz du 10 18. Jednak f2(10 7 ) jest rz du 10 14, wi c dokªadno± wzgl dna jest rz du 10 4. Jest to bardzo maªa dokªadno±, jak na arytmetyk podwójnej precyzji, w której bª d wzgl dny oblicze«jest na poziomie 10 16. Mo»emy policzy wzgl dny bª d wzgl dem f2(10 7 ): abs ( ( f 1 (1 e 7) f 2 (1 e 7))/ f 2 (1 e 7)) i otrzymamy 7.9928e 04. 4.1.2 Obliczanie funkcji z rozwini cia w szereg Inny przykªad na problemy redukcj cyfr, to obliczanie warto±ci funkcji korzystaj ce z rozwini cia w szereg o wyrazach o ró»nych znakach. Rozpatrzmy funkcj sin(x), która ma nast puj ce rozwini cie w globalnie zbie»ny szereg: sin(x) = x x3 3! + x5 5! x7 7! +.... Zaimplementujmy w octavie funkcj obliczaj c przybli»enie funkcji matematycznej sin(x), korzystaj ce z odpowiedniego obci cia tego rozwini cia dla dowolnego x rzeczywistego. Implementacja tej funkcji b dzie wektorowa, tzn. wywoªanie jej z macierz X jako argumentem zwróci macierz przybli»e«warto±ci sin na odpowiednich elementach macierzy X. function y=n a s z s i n ( x,n=300) #obliczamy wartosc s i n ( x ) #k o r z y s t a j a c z r o z w i n i e c i a w s z e r e g : #x x^3/3!+x ^5/5!...( 1)^( k+1) x^{2k+1}/(2k +1)!+... #N i l o s c wyrazow w s z e r e g u domyslnie 300 kx= x. x ; y=x ; for k=1:n, x=x. kx. / ( ( 2 k ) (2 k +1)); y+=x ; endfor endfunction 39
Rysunek 4.2: [11π, 13π] Wykres funkcji sinus obliczanej z rozwini cia w szereg na Przetestujmy nasz funkcj na [ π, π]. w=linspace( pi, pi ) ; plot (w, sin (w), " ; s i n ; ",w, n a s z s i n (w), " ; n a s z s i n ; " ) Na wykresie nie wida ró»nicy. Przetestujmy nasz funkcj dla wi kszych argumentów: [11 π, 13 π]: w=linspace (11 pi,13 pi ) ; plot (w, sin (w), " ; s i n ; ",w, n a s z s i n (w), " ; n a s z s i n ; " ) Wida z rysunku 4.2,»e rozwijanie w szereg nie zawsze ma sens z powodu wªasno±ci arytmetyki zmiennopozycyjnej. Mo»na postawi pytanie, czy w rozwini ciu nie byªo za maªo wyrazów szeregu? w=linspace (11 pi,13 pi ) ; plot (w, sin (w), " ; s i n ; ",w, n a s z s i n (w, 1 0 0 0 0 0 ), " ; n a s z s i n ; " ) Prosz sprawdzi,»e zwi kszenie ilo±ci wyrazów szeregu nic nie zmieniªo. 40
Rysunek 4.3: Wykres bª du w skali póªlogarytmicznej obliczania funkcji sinus z rozwini cia w szereg Popatrzmy, jak ro±nie bª d na skali logarytmicznej, por. rysunek 4.3: w=linspace (eps,13 pi, 1 0 0 0 ) ; semilogy (w, abs ( sin (w) n a s z s i n (w) ) ) Bª d w skali logarytmicznej ro±nie liniowo. To oznacza,»e bª d ro±nie wykªadniczo. 4.1.3 Obliczanie przybli»onej warto±ci pochodnej Kolejnym przykªadem sytuacji, w której mog pojawi si problemy, to obliczanie pochodnej za pomoc ilorazów ró»nicowych, czyli wprost z denicji. Przetestujmy przybli»one obliczanie pochodnej z denicji, czyli ze wzoru: f (x) f(x + h) f(x). h Wydawaªoby si,»e im h jest mniejsze, tym lepsze przybli»enie otrzymamy. Ale np. dla f(x) = sin(x) z x = 1 i h < eps, np. dla h = eps/2, otrzymamy 41
Rysunek 4.4: Wykres bª du przy obliczaniu pochodnej ilorazem ró»nicowym dsin() dla x = 1 w zale»no±ci od h. w arytmetyce : Sprawd¹my: > h=eps/2 h = 1.1102 e 16 > sin (1+h) sin ( 1 ) ans = 0 #c z y na pewno >sin (1+h)==sin ( 1 ) ans=1 fl(x + h) = fl(1 + h) = 1. Czyli rzeczywi±cie h nie mo»e by dowolnie maªe. Spróbujmy znale¹ dla tego przykªadu optymalne h postaci h = 2 n eksperymentalnie. f=@sin ; h=1;x=1; 42
Rysunek 4.5: Wykres bª du przy obliczaniu pochodnej ilorazem ró»nicowym dsin() dla x = 1 w zale»no±ci od h w skali póªlogarytmicznej fx=f ( x ) ; dfx=cos ( x ) ; er=zeros ( 5 3, 1 ) ; eropt=er (1)=abs ( ( f ( x+h) fx )/h dfx ) ; hopt=h ; n=nopt =0; while (h>=eps ) h/=2; n++; er (n)=abs ( ( f ( x+h) fx )/h dfx ) ; i f ( er (n)< eropt ) eropt=er (n ) ; nopt=n ; hopt=h ; endwhile printf ( " optymalne h=%g=2^( %d)\n", hopt, nopt ) ; plot ( er ) ; 43
Na wykresie nie wida dokªadnie, por. rysunek 4.4, gdzie jest minimum. Na wykresie w skali póª-logarytmicznej minimum jest widoczne, por. rysunek 4.5: semilogy ( er ) Widzimy,»e optymalne h w tym przypadku jest rz du 2 27, czyli ok 10 9. Mo»na powtórzy te same obliczenia dla przybli»ania pochodnej za pomoc tzw. ilorazu centralnego: f (x) f(x + h) f(x h). 2h W kolejnych rozdziaªach b dziemy omawiali wpªyw arytmetyki zmiennopozycyjnej na wyniki oblicze«dla konkretnych zada«. 44