Wprowadzenie
Liczby przybliżone
Na zajęciach z Technologii Informacyjnych pojawił się problem arytmetyki liczb obarczonych błędem bezwzględnym.
Liczba przybliżona według używanej definicji to para, na którą składa się wartośc przybliżóna ($a$) i jej błąd bezwzględny ($\Delta a$).
Aby móc korzstać z takich „tworów" w języku C można użyć
struktur.
Tworzymy nowy typ danych (real
) będący strukturą o dwu składowych: val
(wartość przybliżona) i err (błąd bezwzględny).
Zatem definiujemy struct real
jako:
struct real {
double val;
double err;
}
struct real x; // a tu deklarujemy zmienną takiego typu
x.val
przechowuje wartość liczby, x.err
przechowuje jej błąd
bezwzględny.
Strukture struct real
powinna być zadeklarowana jako struktura
globalna (to znaczy na zewnątrz funkcji main()
).
Ponieważ na zmiennych typu nie można wykonywać bezpośrednio żadnych operacji — należy przygotować odpowiednie funkcje.
Należy stworzyć bibliotekę (zestaw funkcji) operacji arytmetycznych (co najmniej suma, różnica, iloczyn, iloraz) na takich liczbach, która oprócz wykonywania samych działań, będzie za każdym razem wyliczała błąd bezwzględny wyniku.
Prototyp funkcji suma może wyglądać tak:
struct real suma(struct real a, struct real b);
A odpowiednikiem prostego działania $$y=\frac{a+b}{cd}$$ będzie
y = iloraz(suma(a, b), iloczyn(c, d));
Zaokrąglanie
Biblioteka powinna też być wyposażona w funkcje poprawnego zaokrąglania wyniku (działającą dla dowolnych liczb: zaokrąglenie z dokładnością …,tysięcy, setek, dziesiątek, jedności, dziesiątych, setnych, tysięcznych…). Podczas zaokrąglania powinien być odpowiednio korygowany błąd bezwzględny. Prototyp funkcji zaokrąglania wyglądać może jakoś tak:
struct real zaokr(struct real wartosc, int n);
gdzie wartosc to wartość przybliżona, którą chcemy zaokrąglić, a n to
liczba cyfr znaczących, która nas interesuje. Dla n = 0
— chcemy
tylko wartości całkowitej (dokładność jednostek, $10^0$), n = 1
—
dokładność do dziesiątek ($10^1$), a n = -2
to dwie cyfry po kropce
dziesiętnej (dokładność do setnych części $10^{-2}$). Stusujemy regułę
„zaokrąglania poprawnego" (jeżeli odrzucana cyfra jest z zakresu 0 do 4
to pozostająca cyfra jest bez zmian, w przeciwnym razie pozostającą
cyfrę zwiększamy o 1).
Zaokrąglenie do pełnych jednostek można zrealizować w sposób następujący. Jeżeli $x$ to dowolna liczba to część_całkowita($x +0.5$) da nam w rezultacie poprawnie zaokrągloną (do jednostek) wartość.
Do wyznaczania części całkowitej służą funkcje trunc, ceil, floor, round,…
Polecenie typedef
Ponieważ ciągłe pisanie struct real
może wydawać się męczące, można
sobie ułatwić życie korzystając z polecenia
typedef
,
które pozwala stworzyć nowy typ (na przykład strukturalny):
typedef struct{
double val;
double err;
} real;
tworzy nowy typ (o nazwie real) równoważny używanemu wcześniej
struct real
.
I teraz, prototyp funkcji suma()
będzie wyglądał tak:
real suma(real a, real b);
Zadania do wykonania
Biblioteka funkcji arytmetycznych.
Przetestowana funkcja realizująca operację zaokrąglenia.
Powtórzenia obliczeń zaprezentowanych na slajdach wykładu (Przykład) (lub, jeżeli to za trudne, jakieś inne „sensowne" obliczenia — objętość jakiejś popularnej bryły geometrycznej, rozwiązanie równania kwadratowego — potrzebne będzie oszacowanie błędu pierwiastka,…).