Autor Wątek: Błędy obliczeń  (Przeczytany 2568 razy)

Offline Vector

  • Użytkownik

# Październik 20, 2013, 20:47:07
Cześć,
W programie wykonuje kilkanaście obliczeń elementarnych tj. + - * /, po wykonaniu operacji dostaje wyniku typu: 15.0000000000191, 3.99999999999999998 etc. Co mogę na to poradzić abym otrzymywał prawidlowe wyniki?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Liosan

  • Redaktor

  • +1
# Październik 20, 2013, 20:51:28
To nie są błędy obliczeń tylko błędy reprezentacji. Liczba zmiennoprzecinkowa nie jest w stanie reprezentować liczb całkowitych z pełną precyzją.

Jak sobie radzić? Zaokrąglać przed wyświetleniem, albo wyświetlać tylko 2 cyfry po przecinku przy okazji formatowania tekstu.

Liosan

Offline Xion

  • Moderator
    • xion.log

  • +1
# Październik 20, 2013, 20:53:50
Względnie wykonywać obliczenia na liczbach stałoprzecinkowych, jeśli dokładność jest ważna.

Offline Vector

  • Użytkownik

# Październik 20, 2013, 21:04:42
Moja aplikacja implementuje obliczenia numeryczne więc to zaokrąglanie musi być w miarę inteligentne tzn. zaokrąglać wtedy kiedy 'trzeba', na razie nie mam pomysłu na to.

Offline JasonVoorhees

  • Użytkownik
    • The Immortal Life of the Son of Jay

  • +1
# Październik 20, 2013, 21:50:17
Weź sobie klasę, która wykonuje dokładne obliczenia. W Javie masz BigDecimal:

http://easyprograming.com/index.php/java/4-how-to-do-arithmetic-operations-with-exact-precision-decimal-points-in-java

Jest to dużo wolniejsze niż sprzętowe float i double, ale za to precyzyjne.

Ewentualnie robisz klasę typu fraction i wszystkie liczby przechowujesz jako ułamki zwykłe i na nich też przeprowadzasz operacje. Nie wiem, czy Java jest standardowo wyposażona w coś takiego, ale w Pythonie widziałem:

>>> from fractions import Fraction
>>> a=Fraction(654,3426)*Fraction(5654,234)
>>> a
Fraction(308143, 66807)
« Ostatnia zmiana: Październik 20, 2013, 21:56:03 wysłana przez JasonVoorhees »

Offline Xender

  • Użytkownik

  • +1
# Październik 22, 2013, 00:54:43
Moja aplikacja implementuje obliczenia numeryczne więc to zaokrąglanie musi być w miarę inteligentne tzn. zaokrąglać wtedy kiedy 'trzeba', na razie nie mam pomysłu na to.
A kiedy "trzeba"? Bo to dość kluczowa sprawa. ;)

No i oprócz samej reprezentacji dochodzi kwestia stabilności numerycznej algorytmów - te same rzeczy można czasami obliczyć na różne sposoby, akumulując po drodze więcej lub mniej błędów zaokrąglania (które mogą się kumulować, a chyba nawet też znosić, zależnie od sytuacji).

Offline Xion

  • Moderator
    • xion.log

# Październik 23, 2013, 00:20:25
Błędy numeryczne nie mogą się znosić, jeśli ich rozkład na przedziale niepewności jest jednostajny. Nie słyszałem, żeby przy szacowaniu tychże błędów przyjmowano inne założenie.

Offline Kelesh

  • Użytkownik

# Październik 23, 2013, 02:09:23
Albo zastosuj algorytm Kahana:
http://pl.wikipedia.org/wiki/Algorytm_sumacyjny_Kahana

Da Ci możliwie dokładny wynik, jaki da się uzyskać na liczbach zmiennoprzecinkowych.