WinstonSmith ha scritto:
Il mio metodo:
public static Double formatDouble(Double value) {
if (value==null) return 0.0;
return new BigDecimal(value).setScale(2 , BigDecimal.ROUND_DOWN).doubleValue();
}
Attenzione ad alcune cose (per dire, in generale):
1) Quando crei un BigDecimal da un double, il valore double rappresentato nel BigDecimal ha TUTTA la precisione possibile per il numero di bit del double.
Se provi:
double d = 12.46;
System.out.println(d);
System.out.println(new BigDecimal(d));
Il primo stampa 12.46
Ma il secondo stampa 12.46000000000000085265128291212022304534912109375 !!!
Perché? Perché BigDecimal essendo a precisione arbitraria è in grado di rappresentare con esattezza il valore del double, che NON è 12.46 (non può esserlo) ma esattamente quello dato dal BigDecimal.
2) Il metodo setScale(int newScale, int roundingMode) è "deprecato" dal JDK 9. Dovresti usare l'altro:
setScale?(int newScale,
RoundingMode roundingMode)
Se usi <= JDK 8 ok, lì non è ancora deprecato ma se aggiorni già, è meglio.
Detto questo, sì tecnicamente è corretto, perché il round DOWN sostanzialmente "tronca" i decimali senza mai fare alcuna altra logica particolare.
Una alternativa per non usare BigDecimal è quella più classica: il double * 100, poi fai floor() poi dividi per 100. Ma ovviamente entrano in gioco i limiti del double e delle operazioni in floating-point (che comunque va ragionevolmente sempre bene).
Nota bene che i rounding DOWN e FLOOR si comportano in maniera differente sui numeri negativi.
WinstonSmith ha scritto:
Qui invece devo formattare a stringa un Double, sempre con 2 decimali e senza arrotondamenti per eccesso o difetto, anche qui dai test fatti mi sembra ok ma ho dei dubbi:
Attenzione perché se vuoi "senza arrotondamenti per eccesso o difetto", non basta. I DecimalFormat
per default arrotondano con logica HALF_EVEN (è scritto nel javadoc). Quindi se vuoi arrotondare diversamente (es. DOWN), va impostato appositamente.
P.S. nota finale: va bene riusare il DecimalFormat fornito dal tuo getFormatter() ma solo nel contesto di un singolo thread. I Number/DecimalFormat non sono thread-safe. Per usarli concorrentemente da più thread ci vuole sincronizzazione apposita.