MN01LAB: 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 | |||
--> | --> | ||
\cwiczenia{Eksperymenty ze środowiskiem obliczeń numerycznych} | |||
W Linuxie czas działania programu można zbadać poleceniem <code>time</code>. | W Linuxie czas działania programu można zbadać poleceniem <code style="color: #666">time</code>. | ||
<div style="margin-top:1em; padding-top,padding-bottom:1em;"> | <div style="margin-top:1em; padding-top,padding-bottom:1em;"> | ||
Linia 11: | Linia 14: | ||
<div class="exercise"> | <div class="exercise"> | ||
Który z | Który z poniższych programów wykona się szybciej? | ||
<div | |||
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>x = 1.0; | |||
x = 1.0; | |||
for( i = 0; i < N; i++) | for( i = 0; i < N; i++) | ||
x = x/3.0; | x = x/3.0; | ||
Linia 20: | Linia 22: | ||
czy | czy | ||
<div | <div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>x = 1.0; f = 1.0/3.0; | ||
x = 1.0; f = 1.0/3.0; | |||
for( i = 0; i < N; i++) | for( i = 0; i < N; i++) | ||
x = x*f; | x = x*f; | ||
Linia 31: | Linia 31: | ||
<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"> | ||
Oczywiście, szybszy będzie program nie wykorzystujący dzielenia. Optymalizujący | Oczywiście, szybszy będzie program nie wykorzystujący dzielenia. Optymalizujący | ||
kompilator (<code>gcc -O3</code>) strawi, a nawet będzie jeszcze bardziej zadowolony z pozornie | kompilator (<code style="color: #666">gcc -O3</code>) strawi, a nawet będzie jeszcze bardziej zadowolony z pozornie | ||
rozrzutnego kodu | rozrzutnego kodu | ||
<div | <div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>x = 1.0; | ||
x = 1.0; | |||
for( i = 0; i < N; i++) | for( i = 0; i < N; i++) | ||
x = x*(1.0/3.0); | x = x*(1.0/3.0); | ||
Linia 76: | Linia 74: | ||
<div class="exercise"> | <div class="exercise"> | ||
Pomyśl jak obliczać, korzystając jedynie z czterech działań podstawowych: <math>\displaystyle +,\, | Pomyśl, jak obliczać, korzystając jedynie z czterech działań podstawowych: <math>\displaystyle +,\, | ||
-, \, \times, \, \div</math>, wartość funkcji <code>exp(</code><math>\displaystyle x</math><code>)</code> = <math>\displaystyle e^x</math> dla | -, \, \times, \, \div</math>, wartość funkcji <code>exp(</code><math>\displaystyle x</math><code>)</code> = <math>\displaystyle e^x</math> dla | ||
dowolnych <math>\displaystyle x</math> rzeczywistych. Naszym kryterium jest, by <math>\displaystyle |e^x - \exp(x)| \leq | dowolnych <math>\displaystyle x</math> rzeczywistych. Naszym kryterium jest, by <math>\displaystyle |e^x - \exp(x)| \leq | ||
Linia 82: | Linia 80: | ||
<math>\displaystyle \epsilon</math>. | <math>\displaystyle \epsilon</math>. | ||
Wykonaj eksperymenty w C lub w Octave pokazujące koszt metody w zależności od | Wykonaj eksperymenty w C lub w Octave, pokazujące koszt metody w zależności od | ||
<math>\displaystyle x</math> oraz w zależności od <math>\displaystyle \epsilon</math>. Przeprowadź też sekwencję testów | <math>\displaystyle x</math> oraz w zależności od <math>\displaystyle \epsilon</math>. Przeprowadź też sekwencję testów | ||
potwierdzających twoje rachunki co do oczekiwanej dokładności (porównując się z | potwierdzających twoje rachunki co do oczekiwanej dokładności (porównując się z | ||
funkcją biblioteczną). W C możesz korzystać ze stałej <code>M_E</code> <math>\displaystyle \approx e = | funkcją biblioteczną). W C możesz korzystać ze stałej <code>M_E</code> <math>\displaystyle \approx e = | ||
\exp(1)</math> zdefiniowanej w pliku nagłówkowym <code>math.h</code>. | \exp(1)</math>, zdefiniowanej w pliku nagłówkowym <code style="color: #666">math.h</code>. | ||
</div></div> | </div></div> | ||
Linia 126: | Linia 124: | ||
<center><math>\displaystyle | <center><math>\displaystyle | ||
\left | \left|e^x - \exp(x,N) \right| \leq \frac{|x|^{N+1}}{(N+1)!}, | ||
</math></center> | </math></center> | ||
Linia 134: | Linia 132: | ||
samodzielnie): | samodzielnie): | ||
<div | <div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre>function [y, N] = expa(x, epsilon) | ||
function [y, N] = expa(x, epsilon) | |||
y = skladnik = 1.0; N = 1; | y = skladnik = 1.0; N = 1; | ||
while (abs(skladnik) > epsilon) | while (abs(skladnik) > epsilon) | ||
Linia 144: | Linia 140: | ||
end | end | ||
end | end | ||
</pre></div> | </pre></div> | ||
Możesz go przetestować pod względem osiąganej dokładności i kosztu, porównując się z | Możesz go przetestować pod względem osiąganej dokładności i kosztu, porównując się z | ||
funkcją biblioteczną: | funkcją biblioteczną: | ||
<div | <div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre>function [blad, relblad, koszt] = testexp(expX, x) | ||
function [blad, relblad, koszt] = testexp(expX, x) | |||
dokladnie = exp(x); | dokladnie = exp(x); | ||
[wartosc, koszt] = feval(expX,x,1e-8); | [wartosc, koszt] = feval(expX,x,1e-8); | ||
Linia 172: | Linia 166: | ||
plot(zakres, relblada, ';blad wzgledny;'); | plot(zakres, relblada, ';blad wzgledny;'); | ||
plot(zakres, blada, ';blad bezwzgledny;'); | plot(zakres, blada, ';blad bezwzgledny;'); | ||
</pre></div> | </pre></div> | ||
Zgodnie z oczekiwaniami, błąd jest poniżej zadanej tolerancji, tutaj | Zgodnie z oczekiwaniami, błąd jest poniżej zadanej tolerancji, tutaj <math>\displaystyle 10^{-8}</math>. | ||
[[Image:MNbladwzglednyexpa.png|thumb| | [[Image:MNbladwzglednyexpa.png|thumb|550px|center|Błąd względny aproksymacji wielomianem Taylora.]] | ||
Koszt aproksymacji rośnie wraz z <math>\displaystyle x</math>: | |||
[[Image:MNkosztexpa.png|thumb| | [[Image:MNkosztexpa.png|thumb|550px|center|Koszt aproksymacji wielomianem Taylora.]] | ||
Niektóre wyniki mogą Cię jednak zaskoczyć: | Niektóre wyniki mogą Cię jednak zaskoczyć: | ||
* Błąd bezwzględny przekracza założoną wartość, gdy <math>\displaystyle \epsilon = 2.2\cdot | * Błąd bezwzględny przekracza założoną wartość, gdy <math>\displaystyle \epsilon = 2.2\cdot 10^{-15}</math>, a błąd względny od pewnego momentu <strong>rośnie</strong> z <math>\displaystyle x</math>. [[Image:MNbladbezwzglednyexpaeps.png|thumb|550px|center|Błąd względny aproksymacji wielomianem Taylora dla zadanej bardzo małej tolerancji błędu.]] | ||
10^{-15}</math>, a błąd względny od pewnego momentu <strong>rośnie</strong> z <math>\displaystyle x</math>. | |||
[[Image:MNbladbezwzglednyexpaeps.png|thumb| | |||
tolerancji błędu.]] | |||
* Nie daje się tak policzyć <math>\displaystyle e^{2006}</math>. | * Nie daje się tak policzyć <math>\displaystyle e^{2006}</math>. | ||
* Wartość <code>expa()</code> może być ujemna dla <math>\displaystyle x<0</math>. | * Wartość <code style="color: #006">expa()</code> może być ujemna dla <math>\displaystyle x<0</math>. | ||
Wyjaśnienie tych szokujących faktów (które nie mają nic wspólnego z błędem w | Wyjaśnienie tych szokujących faktów (które nie mają nic wspólnego z błędem w | ||
implementacji) musisz odłożyć do momentu, gdy bliżej przyjrzymy się temu, <strong>jak</strong> | implementacji) musisz odłożyć do momentu, [[MN03|gdy bliżej przyjrzymy się temu, <strong>jak</strong> | ||
liczy komputer. | liczy komputer]]. | ||
</div></div></div> | </div></div></div> | ||
Linia 200: | Linia 191: | ||
<div class="exercise"> | <div class="exercise"> | ||
Spróbuj obniżyć koszt wyznaczania <math>\displaystyle \exp(x)</math> dla dużych <math>\displaystyle x</math> | Spróbuj obniżyć koszt wyznaczania <math>\displaystyle \exp(x)</math> dla dużych <math>\displaystyle x</math>. | ||
<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"> Rzecz w tym, że dla dużych <math>\displaystyle x</math>, trzeba wziąć bardzo dużo wyrazów w szeregu | ||
Taylora. Czy można tak wykombinować, by w rezultacie wziąć ich mniej? </div> | Taylora. Czy można tak wykombinować, by w rezultacie wziąć ich mniej? </div> | ||
</div></div> | </div></div> | ||
Linia 220: | Linia 211: | ||
Tak więc zadanie redukuje się do wyznaczenia <math>\displaystyle \exp(t)</math> dla <strong>małego</strong> <math>\displaystyle t</math> oraz | Tak więc zadanie redukuje się do wyznaczenia <math>\displaystyle \exp(t)</math> dla <strong>małego</strong> <math>\displaystyle t</math> oraz | ||
do co najwyżej <math>\displaystyle k</math> dodatkowych mnożeń potrzebnych do wyznaczenia całkowitej | do co najwyżej <math>\displaystyle k</math> dodatkowych mnożeń potrzebnych do wyznaczenia całkowitej | ||
potęgi <math>\displaystyle e^k</math> (ile mnożeń <strong>naprawdę</strong> wystarczy?). Pamiętaj, | potęgi <math>\displaystyle e^k</math> (ile mnożeń <strong>naprawdę</strong> wystarczy?). Pamiętaj, przyjęliśmy, że | ||
znamy reprezentację numeryczną liczby <math>\displaystyle e</math>. | znamy reprezentację numeryczną liczby <math>\displaystyle e</math>. | ||
<div | <div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre>[Wersja B] | ||
function [y, N] = expb(x, epsilon) | function [y, N] = expb(x, epsilon) | ||
k = floor(x); t = x - k; | k = floor(x); t = x - k; | ||
Linia 233: | Linia 223: | ||
N += (k+2); | N += (k+2); | ||
end | end | ||
</pre></div> | </pre></div> | ||
[[Image:MNkosztexpab.png|thumb| | [[Image:MNkosztexpab.png|thumb|550px|center|Wersja B jest istotnie tańsza.]] | ||
</div></div></div> | </div></div></div> |
Wersja z 19:58, 28 wrz 2006
\cwiczenia{Eksperymenty ze środowiskiem obliczeń numerycznych}
W Linuxie czas działania programu można zbadać poleceniem time
.
Ćwiczenie
Który z poniższych programów wykona się szybciej?
x = 1.0; for( i = 0; i < N; i++) x = x/3.0;
czy
x = 1.0; f = 1.0/3.0; for( i = 0; i < N; i++) x = x*f;
Ćwiczenie
Napisz program w C, który zapisuje do pliku
- tekstowego
- binarnego
kolejne wartości , gdzie . Następnie porównaj rozmiary plików i możliwości ich odczytania zewnętrznymi narzędziami. Wreszcie, wczytaj liczby z pliku i porównaj je z oryginalnymi wartościami sinusa. Czy możesz wyjaśnić przyczyny różnic?
Powtórz to samo w Octave.
Ćwiczenie: Implementacja funkcji matematycznych
Pomyśl, jak obliczać, korzystając jedynie z czterech działań podstawowych: , wartość funkcji exp(
)
= dla
dowolnych rzeczywistych. Naszym kryterium jest, by , czyli by błąd bezwzględny aproksymacji nie przekroczył zadanego
.
Wykonaj eksperymenty w C lub w Octave, pokazujące koszt metody w zależności od
oraz w zależności od . Przeprowadź też sekwencję testów
potwierdzających twoje rachunki co do oczekiwanej dokładności (porównując się z
funkcją biblioteczną). W C możesz korzystać ze stałej M_E
, zdefiniowanej w pliku nagłówkowym math.h
.
Ćwiczenie: Ciag dalszy
Spróbuj obniżyć koszt wyznaczania dla dużych .