MN01LAB: Różnice pomiędzy wersjami
mNie podano opisu zmian |
m Zastępowanie tekstu – „,↵</math>” na „</math>,” |
||
(Nie pokazano 3 wersji utworzonych przez 2 użytkowników) | |||
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. | ||
Linia 7: | Linia 6: | ||
=Eksperymenty ze środowiskiem obliczeń numerycznych= | =Eksperymenty ze środowiskiem obliczeń numerycznych= | ||
{{powrot |Metody numeryczne | do strony głównej | |||
przedmiotu <strong>Metody numeryczne</strong>}} | |||
<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> | |||
W Linuxie czas działania programu można zbadać poleceniem <code style="color: #666">time</code>. | W Linuxie czas działania programu można zbadać poleceniem <code style="color: #666">time</code>. | ||
Linia 38: | Linia 45: | ||
</pre></div> | </pre></div> | ||
dlatego, że stałą, przez którą trzeba mnożyć <math> | dlatego, że stałą, przez którą trzeba mnożyć <math>x</math>, wyliczy przed wykonaniem | ||
programu. | programu. | ||
Linia 53: | Linia 60: | ||
* binarnego | * binarnego | ||
kolejne wartości <math> | kolejne wartości <math>\sin(\pi\cdot i\cdot 0.4)</math>, gdzie <math>i=0,\ldots, 1024</math>. Następnie porównaj | ||
rozmiary plików i możliwości ich odczytania zewnętrznymi narzędziami. Wreszcie, | 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 | wczytaj liczby z pliku i porównaj je z oryginalnymi wartościami sinusa. Czy | ||
Linia 72: | Linia 79: | ||
<div class="exercise"> | <div class="exercise"> | ||
Pomyśl, jak obliczać, korzystając jedynie z czterech działań podstawowych: <math> | Pomyśl, jak obliczać, korzystając jedynie z czterech działań podstawowych: <math>+,\, | ||
-, \, \times, \, \div</math>, wartość funkcji <code>exp(</code><math> | -, \, \times, \, \div</math>, wartość funkcji <code>exp(</code><math>x</math><code>)</code> = <math>e^x</math> dla | ||
dowolnych <math> | dowolnych <math>x</math> rzeczywistych. Naszym kryterium jest, by <math>|e^x - \exp(x)| \leq | ||
\epsilon</math>, czyli by błąd bezwzględny aproksymacji nie przekroczył zadanego | \epsilon</math>, czyli by błąd bezwzględny aproksymacji nie przekroczył zadanego | ||
<math> | <math>\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> | <math>x</math> oraz w zależności od <math>\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> | funkcją biblioteczną). W C możesz korzystać ze stałej <code>M_E</code> <math>\approx e = | ||
\exp(1)</math>, zdefiniowanej w pliku nagłówkowym <code style="color: #666">math.h</code>. | \exp(1)</math>, zdefiniowanej w pliku nagłówkowym <code style="color: #666">math.h</code>. | ||
Linia 89: | Linia 96: | ||
W pierwszym odruchu myślimy o szeregu definiującym funkcję wykładniczą, | W pierwszym odruchu myślimy o szeregu definiującym funkcję wykładniczą, | ||
<center><math> | <center><math> | ||
e^x = \sum_{n=0}^\infty \frac{x^n}{n!} | e^x = \sum_{n=0}^\infty \frac{x^n}{n!} | ||
</math></center> | </math></center> | ||
Linia 95: | Linia 102: | ||
lub o granicy | lub o granicy | ||
<center><math> | <center><math> | ||
e^x = \lim_{n\rightarrow \infty} \left( 1 + \frac{x}{n}\right)^{\frac{n}{x}} | e^x = \lim_{n\rightarrow \infty} \left( 1 + \frac{x}{n}\right)^{\frac{n}{x}}</math></center> | ||
</math></center> | |||
Drugi pomysł okazuje się niewypałem między innymi dlatego, że musi korzystać z operacji | Drugi pomysł okazuje się niewypałem między innymi dlatego, że musi korzystać z operacji | ||
potęgowania z wykładnikiem rzeczywistym (którą skądinąd najprościej | potęgowania z wykładnikiem rzeczywistym (którą skądinąd najprościej | ||
implementować korzystając m.in. z funkcji <math> | implementować korzystając m.in. z funkcji <math>\exp</math>, jako <math>x^y = \exp(y\cdot \log(x))</math>). | ||
Przyjrzyjmy się więc pierwszemu. | Przyjrzyjmy się więc pierwszemu. | ||
<center><math> | <center><math> | ||
e^x \approx \sum_{n=0}^N \frac{x^n}{n!} | e^x \approx \sum_{n=0}^N \frac{x^n}{n!}</math>,</center> | ||
</math></center> | |||
a dokładniej, ze wzoru na resztę w postaci Lagrange'a, | a dokładniej, ze wzoru na resztę w postaci Lagrange'a, | ||
<center><math> | <center><math> | ||
|e^x - \sum_{n=0}^N \frac{x^n}{n!} | \leq \frac{|\xi|^{N+1}}{(N+1)!} | |e^x - \sum_{n=0}^N \frac{x^n}{n!} | \leq \frac{|\xi|^{N+1}}{(N+1)!}</math></center> | ||
</math></center> | |||
Stąd dostajemy oszacowanie, oznaczając wartość szeregu obciętego na <math> | Stąd dostajemy oszacowanie, oznaczając wartość szeregu obciętego na <math>N</math>-tym | ||
wyrazie, | wyrazie, | ||
<center><math> | <center><math> | ||
\exp(x,N) = \sum_{n=0}^N \frac{x^n}{n!} | \exp(x,N) = \sum_{n=0}^N \frac{x^n}{n!}</math>,</center> | ||
</math></center> | |||
<center><math> | <center><math> | ||
\left|e^x - \exp(x,N) \right| \leq \frac{|x|^{N+1}}{(N+1)!}, | \left|e^x - \exp(x,N) \right| \leq \frac{|x|^{N+1}}{(N+1)!}, | ||
</math></center> | </math></center> | ||
tak więc <math> | tak więc <math>N</math> musi być takie, że <math>\frac{|x|^{N+1}}{(N+1)!} \leq \epsilon</math>. | ||
Poniżej mamy kod, który to realizuje w Octave (analogiczny program w C napisz samodzielnie): | Poniżej mamy kod, który to realizuje w Octave (analogiczny program w C napisz samodzielnie): | ||
Linia 165: | Linia 168: | ||
</pre></div> | </pre></div> | ||
Zgodnie z oczekiwaniami, błąd jest poniżej zadanej tolerancji, tutaj <math> | Zgodnie z oczekiwaniami, błąd jest poniżej zadanej tolerancji, tutaj <math>10^{-8}</math>. | ||
[[Image:MNbladwzglednyexpa.png|thumb|550px|center|Błąd względny aproksymacji wielomianem Taylora.]] | [[Image:MNbladwzglednyexpa.png|thumb|550px|center|Błąd względny aproksymacji wielomianem Taylora.]] | ||
Koszt aproksymacji rośnie wraz z <math> | Koszt aproksymacji rośnie wraz z <math>x</math>: | ||
[[Image:MNkosztexpa.png|thumb|550px|center|Koszt aproksymacji wielomianem Taylora.]] | [[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> | * Błąd bezwzględny przekracza założoną wartość, gdy <math>\epsilon = 2.2\cdot 10^{-15}</math>, a błąd względny od pewnego momentu <strong>rośnie</strong> z <math>x</math>. [[Image:MNbladbezwzglednyexpaeps.png|thumb|550px|center|Błąd względny aproksymacji wielomianem Taylora dla zadanej bardzo małej tolerancji błędu.]] | ||
* Nie daje się tak policzyć <math> | * Nie daje się tak policzyć <math>e^{2006}</math>. | ||
* Wartość <code style="color: #006">expa()</code> może być ujemna dla <math> | * Wartość <code style="color: #006">expa()</code> może być ujemna dla <math>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 | ||
Linia 188: | Linia 191: | ||
<div class="exercise"> | <div class="exercise"> | ||
Spróbuj obniżyć koszt wyznaczania <math> | Spróbuj obniżyć koszt wyznaczania <math>\exp(x)</math> dla dużych <math>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:#f9fff9; padding: 1em"> Rzecz w tym, że dla dużych <math> | <div style="font-size:smaller; background-color:#f9fff9; padding: 1em"> Rzecz w tym, że dla dużych <math>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 199: | Linia 202: | ||
<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"> | ||
Bez zmieniejszenia ogólności, załóżmy, że <math> | Bez zmieniejszenia ogólności, załóżmy, że <math>x\geq 0</math>. | ||
Jeśli <math> | Jeśli <math>x = k + t</math>, gdzie <math>t \in [0,1)</math>, a <math>k</math> jest całkowite, to oczywiście | ||
<center><math> | <center><math> | ||
e^x = e^{k+t} = e^k e^t = e^k \exp(t) | e^x = e^{k+t} = e^k e^t = e^k \exp(t)</math></center> | ||
</math></center> | |||
Tak więc zadanie redukuje się do wyznaczenia <math> | Tak więc zadanie redukuje się do wyznaczenia <math>\exp(t)</math> dla <strong>małego</strong> <math>t</math> oraz | ||
do co najwyżej <math> | do co najwyżej <math>k</math> dodatkowych mnożeń potrzebnych do wyznaczenia całkowitej | ||
potęgi <math> | potęgi <math>e^k</math> (ile mnożeń <strong>naprawdę</strong> wystarczy?). Pamiętaj, przyjęliśmy, że | ||
znamy reprezentację numeryczną liczby <math> | znamy reprezentację numeryczną liczby <math>e</math>. | ||
<div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre># wersja B | <div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre># wersja B |
Aktualna wersja na dzień 21:51, 11 wrz 2023
Eksperymenty ze środowiskiem obliczeń numerycznych
<<< Powrót do strony głównej przedmiotu Metody numeryczne
Oglądaj wskazówki i rozwiązania __SHOWALL__
Ukryj wskazówki i rozwiązania __HIDEALL__
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 .