DecimalFormat e Double.valueOf ()
-
01-10-2019 - |
Domanda
Sto cercando di sbarazzarsi di simboli inutili dopo decimale separatore del mio valore doppio. Lo sto facendo in questo modo:
DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));
Ma quando si esegue questo codice, viene generata:
java.lang.NumberFormatException: For input string: "41251,5"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
at java.lang.Double.valueOf(Double.java:447)
at ...
Per come la vedo, Double.valueOf()
grandi opere con le stringhe come "11.1"
, ma soffoca sulle stringhe come "11,1"
. Come posso ovviare a questo? C'è un modo più elegante poi qualcosa come
Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));
C'è un modo per ignorare il valore di separatore decimale predefinito di classe DecimalFormat
? Eventuali altri pensieri?
Soluzione
Per
sbarazzarsi di simboli inutili dopo decimale separatore del mio valore doppio
si fa realtà significa che si desidera round per esempio il 5 ° decimale? Poi basta usare
value = Math.round(value*1e5)/1e5;
(naturalmente si può anche Math.floor(value*1e5)/1e5
se si vuole veramente le altre cifre tagliare)
Altri suggerimenti
Il problema è che il formato decimale converte il valore in una stringa localizzata. Sto indovinando che il separatore decimale predefinito per il locale è con un ',
'. Questo accade spesso con i locali francesi o altre parti del mondo.
In sostanza ciò che devi fare è creare il data formattata con il '' separatore in modo Double.valueOf
può leggere. Come indicato dai commenti, è possibile utilizzare lo stesso formato per analizzare il valore e invece di usare Double.valueOf
.
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
Il fatto che i vostri usi stringa di formattazione .
come separatore decimale, mentre l'eccezione si lamenta di punti ,
ad un problema Locale; cioè DecimalFormat utilizza un diverso Locale per formattare il numero di aspetta Double.valueOf.
In generale, si dovrebbe costruire un NumberFormat
sulla base di una specifica Locale.
Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);
Dalle JavaDocs di DecimalFormat :
Per ottenere un NumberFormat per impostazioni locali specifiche, tra cui la lingua di default, chiamare uno dei metodi di fabbrica di NumberFormat, come getInstance (). In generale, non chiamare i costruttori DecimalFormat direttamente, dal momento che i metodi di fabbrica NumberFormat possono restituire sottoclassi diverse DecimalFormat.
come BalusC punti su , tentare di formattare una doppia come String e quindi analizzare la parte posteriore String al doppio è un odore di codice piuttosto male. Ho il sospetto che si tratta di questioni in cui ci si aspetta un numero a precisione fissa decimale (come ad esempio un importo monetario), ma si esegue in problemi a causa doppio è un numero in virgola mobile, il che significa che molti valori (come 0.1
) non possono essere espressa appunto come un doppio / galleggiante. Se questo è il caso, il modo corretto di gestire un numero decimale a precisione fissa è di usare un BigDecimal
.
Usa Locale.getDefault()
per ottenere il vostro separatore decimale di sistema che è possibile impostare. Non si può avere a diversi separatori allo stesso tempo da quando l'altro è poi di solito usato come seprator per migliaia: 2.001.000,23 <=> 2,001,000.23
Per la ',
' al posto del '.
', che avrebbe dovuto modificare le impostazioni internazionali.
Per il numero di decimali, l'uso setMaximumFractionDigits(int newValue)
.
Per il resto, consultare Javadoc .
Sembra che il tuo uso locale una virgola "" come un decimale separation.To ottenere il "" come separatore decimale, si dovrà dichiarare:
DecimalFormat dFormat =new DecimalFormat("#.#", new DecimalFormatSymbols(Locale.ENGLISH));
Non è possibile modificare la rappresentazione interna di double
/ Double
in quel modo.
Se si desidera cambiare la rappresentazione (umana), basta tenere String
. Così, lasciare che Double#valueOf()
di distanza e usare il risultato di String
DecimalFormat#format()
nella presentazione. Se mai voglia di fare calcoli con esso, si può sempre trasformare di nuovo ad un vero e proprio Double
utilizzando DecimalFormat
e Double#valueOf()
.
A proposito, secondo la vostra lamentano che sto cercando di sbarazzarsi dei simboli inutili dopo decimale separatore del mio valore doppio , siete a conoscenza dei meccanismi interni di numeri in virgola galleggiante? C'è odore un po 'come che si sta utilizzando raddoppia non formattati nello strato di presentazione e che non si rendeva conto che con l'interfaccia utente medio si può semplicemente presentare loro utilizzando DecimalFormat
senza la necessità di riconvertire Double
.
Un po 'legato a questo, ma non è una risposta alla domanda: tenta di passare a BigDecimal invece di doppie e carri allegorici. Stavo facendo un sacco di problema con confronti su quei tipi e ora sto bene ad andare con BigDecimal.
La vera soluzione è: non utilizzare i numeri in virgola mobile per tutto ciò che ha bisogno di essere contati con precisione:
- Se avete a che fare con la moneta, non utilizzare un numero doppio di dollari, utilizzare un numero intero di centesimi.
- Se avete a che fare con le ore di tempo e bisogno di contare quarti d'ora e intervalli di 10 minuti, utilizzare un numero intero di minuti.
Un numero virgola mobile è quasi sempre un'approssimazione di qualche valore reale. Sono adatti per misurazioni e calcolo delle grandezze fisiche (alto grado di precisione) e per artefatti statistici.
Ingannare circa con arrotondamento a virgola mobile a un numero di cifre è un odore di codice:. È uno spreco e non si può mai essere veramente sicuri che il codice funziona correttamente in tutti i casi
La mia funzione di codice:
private static double arrondi(double number){
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
return Double.valueOf(format.format(number));
}