Natknąłem się na dwa sposoby uzyskania obiektu BigDecimal z podwójnego d.
1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
Które podejście byłoby lepsze? Czy valueOf stworzyłoby nowy obiekt?
Ogólnie (nie tylko BigDecimal), co jest zalecane - new czy valueOf?
Dzięki.
java
bigdecimal
Manish Mulani
źródło
źródło
Odpowiedzi:
To są dwa osobne pytania: „Do czego mam używać
BigDecimal
?” i „Co ogólnie robię?”Bo
BigDecimal
: jest to trochę trudne, ponieważ nie robią tego samego .BigDecimal.valueOf(double)
użyje kanonicznąString
reprezentację nadouble
wartość przekazana do instancjiBigDecimal
obiektu. Innymi słowy: wartościąBigDecimal
obiektu będzie to, co zobaczysz, kiedy to zrobiszSystem.out.println(d)
.Jeśli
new BigDecimal(d)
jednak użyjesz ,BigDecimal
spróbuje przedstawićdouble
wartość tak dokładnie, jak to możliwe . Będzie to zazwyczaj powodują dużo więcej cyfr są przechowywane niż chcesz. Ściśle mówiąc, jest to bardziej poprawne niżvalueOf()
, ale jest o wiele mniej intuicyjne.Jest ładne wyjaśnienie tego w JavaDoc:
Ogólnie, jeśli wynik jest taki sam (tj. Nie w przypadku
BigDecimal
, ale w większości innych przypadków), tovalueOf()
powinno być preferowane: może wykonywać buforowanie wspólnych wartości (jak widać naInteger.valueOf()
), a nawet może zmieniać zachowanie buforowania bez osoba dzwoniąca musi zostać zmieniona. zawszenew
utworzy instancję nowej wartości, nawet jeśli nie jest to konieczne (najlepszy przykład: vs. ).new Boolean(true)
Boolean.valueOf(true)
źródło
new BigDecimal()
lepsze niżBigDecimal.valueOf()
?new BigDecimal()
byłby preferowany, a kiedyBigDecimal.valueOf()
byłby preferowany?new BigDecimal(1.0/30.0);
iBigDecimal.valueOf(1.0/30.0)
. Zobacz, który wynik jest rzeczywiście bliższy ułamkowi liczbowemu 1/30.Jeśli używasz swoich
BigDecimal
obiektów do przechowywania wartości walut, zdecydowanie zalecam, aby w swoich obliczeniach NIE wprowadzać żadnych podwójnych wartości.Jak stwierdzono w innej odpowiedzi, istnieją znane problemy z dokładnością związane z podwójnymi wartościami, które będą Cię prześladować.
Gdy już to minie, odpowiedź na twoje pytanie jest prosta. Zawsze używaj metody konstruktora z wartością String jako argumentem konstruktora, ponieważ nie ma
valueOf
metody dlaString
.Jeśli chcesz uzyskać dowód, wypróbuj następujące rozwiązania:
BigDecimal bd1 = new BigDecimal(0.01); BigDecimal bd2 = new BigDecimal("0.01"); System.out.println("bd1 = " + bd1); System.out.println("bd2 = " + bd2);
Otrzymasz następujące dane wyjściowe:
bd1 = 0.01000000000000000020816681711721685132943093776702880859375 bd2 = 0.01
Zobacz także to powiązane pytanie
źródło
Zasadniczo valueOf (double val) robi to:
return new BigDecimal(Double.toString(val));
Dlatego -> tak, zostanie utworzony nowy obiekt :).
Ogólnie myślę, że zależy to od Twojego stylu kodowania. Nie mieszałbym valueOf i „nowego”, jeśli oba są tym samym wynikiem.
źródło
valueOf()
ma bardziej intuicyjne zachowanie, podczas gdynew BigDecimal(d)
ma bardziej poprawne . Wypróbuj oba i zobacz różnicę.new BigDecimal(1) != new BigDecimal(1)
aleBigDecimal.valueOf(1) == BigDecimal.valueOf(1)
BigDecimal
jest niezmienna to powinny być traktowane w ten sam sposób, że prymitywne owijarki (Integer
,Byte
...) iString
są traktowane: tożsamość obiekt nie powinien sprawa do kodu, tylko wartość powinno mieć znaczenia.valueOf()
powinny generalnie być korzystne. Ale pamiętaj, żeBigDecimal.valueOf(double)
nie wykonuje żadnego buforowania (i prawdopodobnie też nie byłoby tego warte).