2013-04-25 17 views
44

Poszukuję najlepszego sposobu na przekonwertowanie numeru na BigDecimal.Konwertuj numer Java na BigDecimal: najlepszy sposób

Czy to wystarczy?

Number number; 
BigDecimal big = new BigDecimal(number.toString()); 

Czy możemy stracić precyzję za pomocą metody toString()?

+2

Twój kod może rzucić 'NumberFormatException' - jeśli' number' to 'Double', który jest Infinity lub NaN http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Double .html # toString (podwójne) –

+0

Dzięki za napiwek! Zapomniałem sprawdzić to –

Odpowiedz

32

To dobrze, pamiętaj, że użycie konstruktora BigDecimal do zadeklarowania wartości może być niebezpieczne, gdy nie jest typu String. Rozważmy poniżej ...

BigDecimal valDouble = new BigDecimal(0.35); 
System.out.println(valDouble); 

To nie będzie drukować 0,35, to będzie to rzeczywiście być ...

0.34999999999999997779553950749686919152736663818359375 

Powiedziałbym rozwiązanie jest chyba najbezpieczniejszym z tego powodu.

+0

Tak, zauważyłem to. Moje obawy dotyczą metody 'toString()' dla 'Double', zastanawiałem się, czy dzięki tej metodzie możemy stracić precyzję. –

+0

Nie, chociaż naturalnie będziesz mieć większą precyzję, jeśli to był BigDecimal. Jeśli chodzi o walutę, zawsze powinieneś robić wszystko, co BigDecimal. Jeśli zostałby zadeklarowany jako BigDecimal, zanim zostanie rzucony z Double, byłoby to najlepsze rozwiązanie w moim odczuciu i całkowicie wyeliminuje podwójne równanie. – david99world

16

Czy możemy stracić precyzję za pomocą metody toString()?

Rodzaj ... Zarówno Float.toString() jak i Double.toString() wysyłają tylko liczbę cyfr po separatorze dziesiętnym, co jest wymagane, aby dane wyjściowe jednoznacznie odpowiadały wartości float lub podwójnej.

Aby użyć przykładu 0.35 w odpowiedzi david99world trzeba brać pod uwagę następujący kod:

BigDecimal bd1 = new BigDecimal(0.35); 

Number n = 0.35; 
BigDecimal bd2 = new BigDecimal(n.toString()); 

System.out.println(bd1); 
System.out.println(bd2); 

Intuicyjny oczekiwanie może być tak, że dwa BigDecimal przypadki są identyczne, ale wynik pokazuje, że nie są one:

0.34999999999999997779553950749686919152736663818359375 
0.35 

Pierwsza linia to dokładna wartość podwójnego, ponieważ 0,35 nie może być dokładnie odwzorowany. Druga linia to 0,35, ponieważ nie potrzeba więcej cyfr ułamkowych, aby przedstawić odrębną wartość. Na przykład. instrukcja 0.34999999999999997779553950749686919152736663818359375 == 0.35 oceni na true.

To nie jest strata precyzji podczas tworzenia BigDecimal, niepewność jest już w twojej "źródłowej" wartości. Problem polega raczej na tym, że dyskretne wartości możliwe za pomocą np. wartość zmiennoprzecinkowa lub podwójna jako źródło niekoniecznie będzie reprezentowana przez dokładny odpowiednik w instancji BigDecimal.