Wiem, że arytmetyka zmiennoprzecinkowa ma problemy z precyzją. Zwykle pokonuję je, przechodząc do stałej liczby dziesiętnej lub po prostu zaniedbując błąd.
Nie wiem jednak, jakie są przyczyny tej niedokładności. Dlaczego jest tak wiele problemów z zaokrąglaniem liczb zmiennoprzecinkowych?
decimal
działa typ .NET . Z drugiej strony punkt stały jest inny. Tak długo, jak twój zasięg jest ograniczony, punkt stały jest dobrą odpowiedzią. Jednak ograniczony zakres sprawia, że punkt stały nie nadaje się do wielu zastosowań matematycznych, a implementacje liczb stałych nie są często dobrze zoptymalizowane sprzętowo.Odpowiedzi:
Wynika to z faktu, że niektóre ułamki potrzebują bardzo dużej (lub nawet nieskończonej) liczby miejsc do wyrażenia bez zaokrąglania. Dotyczy to zarówno notacji dziesiętnych, jak i binarnych. Jeśli ograniczysz liczbę miejsc dziesiętnych do wykorzystania w obliczeniach (i unikniesz wykonywania obliczeń w notacji ułamkowej), będziesz musiał zaokrąglić nawet proste wyrażenie jako 1/3 + 1/3. Zamiast pisać 2/3 w rezultacie, musiałbyś napisać 0.33333 + 0.33333 = 0.66666, który nie jest identyczny z 2/3.
W przypadku komputera liczba cyfr jest ograniczona technicznym charakterem pamięci i rejestrów procesora. Używana wewnętrznie notacja binarna powoduje dodatkowe trudności. Komputery zwykle nie mogą wyrażać liczb w notacji ułamkowej, chociaż niektóre języki programowania dodają tę możliwość, co pozwala do pewnego stopnia uniknąć tych problemów.
Co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej
źródło
Przede wszystkim błędy zaokrąglania wynikają z faktu, że nieskończoność wszystkich liczb rzeczywistych nie może być reprezentowana przez skończoną pamięć komputera , nie mówiąc już o niewielkim wycinku pamięci, takim jak pojedyncza zmienna zmiennoprzecinkowa , tak wiele przechowywanych liczb jest jedynie przybliżeniem liczba, którą mają reprezentować.
Ponieważ istnieje tylko ograniczona liczba wartości, które nie są przybliżeniem, a każda operacja między przybliżeniem a inną liczbą powoduje przybliżenie, błędy zaokrąglania są prawie nieuniknione .
Ważne jest, aby zdać sobie sprawę, kiedy mogą one powodować problem, i podjąć kroki w celu ograniczenia ryzyka .
Oprócz niezbędnej wiedzy Davida Goldberga , którą każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej (ponownie opublikowanej przez Sun / Oracle jako załącznik do Przewodnika po obliczeniach numerycznych ), o której wspomniał Thorsten , dziennik ACCU Overload działał doskonale seria artykułów Richarda Harrisa o Floating Point Blues .
Seria rozpoczęła się od
Richard zaczyna od wyjaśnienia taksonomii liczb rzeczywistych, racjonalnych, irracjonalnych, algebraicznych i transcendentalnych. Następnie wyjaśnia objaśnienia dotyczące reprezentacji IEEE754, zanim przejdzie do błędu anulowania i problemów z kolejnością wykonywania.
Jeśli nie przeczytasz głębiej, będziesz miał doskonałe uziemienie w problemach związanych z liczbami zmiennoprzecinkowymi.
Jeśli chcesz dowiedzieć się więcej, kontynuuje
Następnie przełącza się na próbę pomocy w wyleczeniu bluesa
i na koniec jest
Warto zapoznać się z całą serią artykułów, a przy całkowitej liczbie 66 stron są one nadal mniejsze niż 77 stron artykułu Goldberga .
Chociaż ta seria obejmuje wiele tego samego obszaru, uważam, że jest ona bardziej dostępna niż artykuł Goldberga . Po przeczytaniu wcześniejszych artykułów Richardsa łatwiej zrozumiałem bardziej złożone części artykułu. Po tych wczesnych artykułach Richard rozgrywa się w wielu interesujących obszarach, których nie porusza artykuł Goldberga.
Jak to powiedzą ak wspomniane w komentarzach:
źródło
Cóż, Thorsten ma ostateczny link . Dodałbym:
Każda forma reprezentacji będzie miała błąd zaokrąglania dla pewnej liczby. Spróbuj wyrazić 1/3 w liczbach zmiennoprzecinkowych IEEE lub w systemie dziesiętnym. Żaden nie może tego zrobić dokładnie. Wykracza to poza udzielenie odpowiedzi na pytanie, ale z powodzeniem zastosowałem tę zasadę:
źródło
Wydaje się, że do tej pory nie wspomniano o koncepcjach niestabilnego algorytmu i źle uwarunkowanego problemu . Najpierw zajmę się tym pierwszym, ponieważ wydaje się, że jest to częstsza pułapka dla początkujących numerycy.
Rozważ obliczenie mocy (wzajemności) złotego podziału
φ=0.61803…
; jednym z możliwych sposobów jest skorzystanie z formuły rekurencyjnejφ^n=φ^(n-2)-φ^(n-1)
, zaczynając odφ^0=1
iφ^1=φ
. Jeśli uruchomisz tę rekurencję w swoim ulubionym środowisku komputerowym i porównasz wyniki z dokładnie oszacowanymi mocami, zauważysz powolną erozję znaczących liczb. Oto, co dzieje się na przykład w Mathematica :Podobny wynik dla
φ^41
ma zły znak, a nawet wcześniej, obliczone i rzeczywiste wartości dlaφ^39
udziału nie mają wspólnych cyfr (3.484899258054952
* ^ - 9for the computed version against the true value
7.071019424062048*^-9
). Algorytm jest więc niestabilny i nie należy używać tej formuły rekurencyjnej w niedokładnej arytmetyki. Wynika to z wrodzonej natury formuły rekurencyjnej: istnieje rozwiązanie „zanikające” i „rosnące” tej rekurencji i próbuje się obliczyć rozwiązanie „rozkładające się” według rozwiązania naprzód, gdy istnieje alternatywne rozwiązanie „rosnące” na smutek numeryczny. Należy zatem upewnić się, że jego / jej algorytmy numeryczne są stabilne.Przejdźmy teraz do koncepcji źle uwarunkowanego problemu: chociaż może istnieć stabilny sposób zrobienia czegoś numerycznie, bardzo możliwe, że Twój problem nie może zostać rozwiązany przez algorytm. Jest to wina samego problemu, a nie metody rozwiązania. Kanonicznym przykładem numerycznym jest rozwiązanie równań liniowych obejmujących tak zwaną „macierz Hilberta”:
Matryca jest kanonicznym przykładem źle uwarunkowanej matrycy: próba rozwiązania układu za pomocą dużej matrycy Hilberta może zwrócić niedokładne rozwiązanie.
Oto demonstracja Mathematica : porównaj wyniki dokładnej arytmetyki
i niedokładna arytmetyka
(Jeśli wypróbowałeś to w Mathematica , zauważysz kilka komunikatów o błędach ostrzegających o pojawieniu się złego warunkowania).
W obu przypadkach zwykłe zwiększenie precyzji nie jest lekarstwem; opóźni to nieuchronną erozję liczb.
Z tym możesz się spotkać. Rozwiązania mogą być trudne: po pierwsze albo wrócisz do deski kreślarskiej, albo przejrzysz czasopisma / książki / cokolwiek, aby znaleźć, czy ktoś wymyślił lepsze rozwiązanie niż ty; po drugie, albo poddajesz się, albo przeformułowujesz swój problem na coś łatwiejszego do rozwiązania.
Zostawię ci cytat z Dianne O'Leary:
źródło
ponieważ podstawowych liczb dziesiętnych nie można wyrazić w podstawie 2
lub innymi słowy 1/10 nie może zostać przekształcony w ułamek o potędze 2 w mianowniku (którym w istocie są liczby zmiennoprzecinkowe)
źródło
9*3.3333333
w systemie dziesiętnym i dopasuj go do9*3 1/3
.1 + .1 != .2
ponieważ używane jest zmiennoprzecinkowe kodowanie binarne, a nie dziesiętne.1.0/3.0*3.0 != 1.0
ponieważ stosowane jest zmiennoprzecinkowe kodowanie binarne, a nie trójkowe.W matematyce istnieje nieskończenie wiele liczb wymiernych. Zmienna 32-bitowa może mieć tylko 2 32 różne wartości, a zmienna 64-bitowa tylko 2 64 wartości. Dlatego istnieje nieskończenie wiele liczb wymiernych, które nie mają dokładnej reprezentacji.
Moglibyśmy wymyślić schematy, które pozwoliłyby nam idealnie reprezentować 1/3 lub 1/100. Okazuje się, że dla wielu praktycznych celów nie jest to zbyt przydatne. Jest jeden wielki wyjątek: w finansach często pojawiają się ułamki dziesiętne. Dzieje się tak głównie dlatego, że finanse są zasadniczo działalnością ludzką, a nie fizyczną.
Dlatego zazwyczaj wybieramy binarne zmiennoprzecinkowe i zaokrąglamy każdą wartość, której nie można przedstawić w postaci binarnej. Ale w finansach czasami wybieramy zmiennoprzecinkowe dziesiętne i zaokrąglamy wartości do najbliższej wartości dziesiętnej.
źródło
"√2"
. (Mój stary kalkulator HP-48 był w stanie to zrobić, a dokładność tej wartości do kwadratu dała dokładnie wynik2.0
). Istnieje tylko policzalna nieskończoność reprezentowalnych liczb rzeczywistych dla dowolnej skończonej reprezentacji - ale żadne obliczenia nie mogą dać liczby, która nie jest, w zasadzie reprezentatywny. W praktyce binarna zmiennoprzecinkowa drastycznie ogranicza zbiór reprezentatywnych liczb, z korzyścią niesamowitej prędkości i niewielkiej pamięci względem reprezentacji symbolicznych.jedynym naprawdę oczywistym „problemem zaokrąglania” liczb zmiennoprzecinkowych, o którym myślę, są filtry średniej ruchomej:
$$ \ begin {align} y [n] & = \ frac {1} {N} \ sum \ limit_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$
aby to działało bez narastania hałasu, musisz upewnić się, że $ x [n] $ dodany w bieżących próbkach jest dokładnie taki sam jak $ x [nN] $, który odejmiesz w próbkach $ N $ przyszłość. jeśli tak nie jest, to co jest inne, to mała gnójka, która utknęła w linii opóźnienia i nigdy nie wyjdzie. to dlatego, że ten filtr średniej ruchomej jest faktycznie zbudowany z IIR, który ma marginalnie stabilny biegun przy $ z = 1 $ i zero, które anuluje go wewnątrz. ale jest to integrator i wszelkie bzdury, które zostaną zintegrowane, a nie całkowicie usunięte, będą istnieć w sumie integratora na zawsze. w tym przypadku punkt stały nie ma tego samego problemu, co liczby zmiennoprzecinkowe.
źródło