Kategorie szkoleń | Egzaminy | Kontakt

Odpowiedź (1)

  • 1
Pytanie może wydawać się banalne.
Wystarczy przecież chwila i kartka papieru, aby udzielić właściwej odpowiedzi: 0.025 * 21.003 = 0.525075
Zapewne jeszcze szybciej uzyskamy wynik pisząc program w Javie:
...
System.out.println(0.025 * 21.003);
...
I tu czeka nas niespodzianka. Wynik jaki otrzymamy to: 0.5250750000000001
Skąd ta niedokładność? Przecież nie wykonujemy obliczeń na astronomicznych liczbach?

Przyczyna leży w reprezentacji liczb zmiennoprzecinkowych. Literały zmiennoprzecinowe w Javie zajmują 8 bajtów i nie są w stanie reprezentować wszystkich liczb rzeczywistych (w sumie zbiór ten ogranicza się do 264 różnych wartości). To samo dotyczy operacji arytmetycznych na liczbach zmiennoprzecinkowych - są one wykonywane z ograniczoną precyzją i wyniki mogą być obarczone błędami zaokrągleń. Warto nadmienić, że problem ma charakter ogólniejszy i nie jest  związany z Javą, ale arytmetyką zmiennoprzecinkową na liczbach o ograniczonym rozmiarze.

W zadaniach dnia codziennego możemy pogodzić się z takimi niedoskonałościami, ale w aplikacjach księgowych lub bankowych takie "zaokrąglenia" są niedopuszczalne. Na szczęście w Javie mamy rozwiązanie, które jest w stanie wyeliminować błędy arytmetyki zmiennoprzecinkowej spowodowane ograniczonym rozmiarem typów danych. W takich sytuacjach należy operacje wykonywać na obiektach klasy java.math.BigDecimal
Klasa daje użytkownikowi pełną kontrolę nad precyzją wykonywanych obliczeń.
Poniższy kod prezentuje sposób wykonania obliczeń w "dokładny" sposób:
BigDecimal bd1 = BigDecimal.valueOf(0.025);
BigDecimal bd2 = BigDecimal.valueOf(21.003);
System.out.println(bd1.multiply(bd2));  // = 0.525075
  • Odpowiedział
  • @ | 26.06.2013
  • TRENER MODERATOR ALTKOM AKADEMII