Działania na BigDecimal

Działania na BigDecimal
PA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 43
0

Mam taki kawałek kodu:

Kopiuj
  BigDecimal year = new BigDecimal(12);

  return estimatedSavingsInYearScale
                .divide(year, 2, BigDecimal.ROUND_HALF_UP)
                .multiply(proposalContractMonthLength);
 

Gdzie jeśli np. estimatedSavingsInYearScale jest równy 16854.20 a proposalContractMonthLength jest równy 12,
to mój wynik jest równych 16854.16.

W jaki sposób podejść do tego aby wyjściowa liczba pozostała bez zmian ?

szarotka
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 555
3

Możesz najpierw pomnożyć, a potem podzielić i problem zaokrąglenia zniknie.

bogdans
  • Rejestracja: dni
  • Ostatnio: dni
0

Niepotrzebnie zaokrąglasz wynik dzielenia do dwóch miejsc po przecinku.

PA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 43
0

@bogdans

Zaokrąglam ponieważ chcę zaprezentować wynik do dwóch miejsc po przecinku. Jak podejść inaczej do tego ?

PA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 43
0

Mam podobne działania które mają o wiele więcej dzielenia i mnożenia. Tam jak porównam wynik do tego co excel liczy to są znaczne różnice...

bogdans
  • Rejestracja: dni
  • Ostatnio: dni
2

Jak podejść inaczej do tego?
Nie możesz zaokrąglać wyników pośrednich. Końcowych też nie powinieneś, ogranicz się do sformatowania wypisywanych wyników.

bogdans
  • Rejestracja: dni
  • Ostatnio: dni
0

Skoro nie potrzebujesz dużej dokładności, to dlaczego korzystasz z typu BigDecimal?

PA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 43
0

Potrzebuję dużej precyzji ale jednocześnie chcę prezentować wyniki tylko do dwóch miejsc po przecinku. Co więcej chciał bym przed wysłaniem do widoku już dokonać zaaokrągelnia.

KA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 51
1

BigDecimal jest immutable, więc każda operacja zwraca nowy obiekt. Zatem to:

Kopiuj
new BigDecimal(9).divide(new BigDecimal(2), BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(2))

działa tak, że 9/2 zawraca 5, a kolejnym działaniem jest 5*2, co daje 10 zamiast oczekiwanego 9. Tak, jak już napisano - nie zaokrąglaj w trakcie liczenia.

Poza tym, używasz konstruktora BigDecimal z doublem zamiast ze Stringiem, więc też tracisz precyzję. Porównaj:

Kopiuj
BigDecimal highPrecisionVal1 = new BigDecimal("3");
BigDecimal highPrecisionVal2 = new BigDecimal("0.1");

BigDecimal lowPrecisionVal1 = new BigDecimal(0.3);
BigDecimal lowPrecisionVal2 = new BigDecimal(0.1);

System.out.println(highPrecisionVal1.multiply(highPrecisionVal2));
System.out.println(lowPrecisionVal1.multiply(lowPrecisionVal2));
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0
bogdans napisał(a):

Jak podejść inaczej do tego?
Nie możesz zaokrąglać wyników pośrednich. Końcowych też nie powinieneś, ogranicz się do sformatowania wypisywanych wyników.

jak z pomocą BigDecimal bez zaokrąglenia zrobisz 1/3 to poleci exception ArithmeticException.
https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divide(java.math.BigDecimal)

KA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 51
0

Hm, racja. To wtedy poratuje odpowiednio duży parametr scale przy dzieleniu.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.