2010-08-09 17 views
6

Dato il seguente codice, mi aspetto che restituisca "float = 32000.0001". Invece, restituisce "float = 32000.0".Arrotondamento in java Float.parseFloat

System.out.println("float = "+Float.parseFloat("32000.0001")); 

C'è qualcosa che posso fare per prevenire/controllare l'arrotondamento? Voglio il valore completo restituito senza arrotondamento.

risposta

7

Un valore float ha solo 24 bit di precisione, il che non è sufficiente per contenere il numero di cifre nel valore. L'arrotondamento non è dovuto all'analisi, ma alla dimensione del numero. Devi usare un double se hai bisogno di virgola mobile, o usare BigDecimal se hai bisogno di precisione arbitraria.

1

Se le posizioni decimali ti interessano, vorrei fortemente consiglia di utilizzare BigDecimal invece.

Così com'è, non è del tutto chiaro per me (senza controllare) se il problema è l'analisi da una stringa o la formattazione in una stringa.

EDIT: In questo caso ho il forte sospetto che è l'arrotondamento su analisi ... dato che float ha solo 7 (garantiti) cifre significative e si sta cercando di preservare 9.

+0

ho rotto la linea singola in più righe e corse attraverso il debugger. Il problema sembra essere nell'analisi. Sembra che Float.parseFloat abbia arrotondato a "32000.0" – Shane

+0

@Shane: Supponiamo ancora che il debugger ti mostri il valore esatto, sospetto. –

+0

cambiando a BigDecimal fissare i miei problemi con i decimali – jeff

0

Se si vuole evitare arrotondamenti, utilizzare BigDecimal. I tipi primitivi float e double sono più veloci ma non possono rappresentare molti valori decimali comuni.

0

I galleggianti e i doppi sono limitati. Sono solo in grado di rappresentare accuratamente le parti frazionarie dei numeri come somma di due frazioni di base. La parte frazionaria può essere completamente rappresentata come la somma di alcune serie come:

1/2 + 0/4 + 1/8 + 1/16 + ...

Purtroppo ci sono un gran numero di comunemente numeri utilizzati, che non può essere pienamente rappresentati, come:

1/3, 1/7, 1/9, 5/11 ecc

È necessario considerare se il numero può essere rappresentato in modo accurato prima di preoccuparsi di arrotondamento. Se questo tipo di accuratezza è di estrema importanza, è necessario cercare una soluzione non Float o non Double.

Esistono librerie decimali binarie che eseguiranno con precisione tali calcoli. Tendono ad essere più lenti da calcolare, perché non c'è hardware specializzato per accelerare i loro calcoli. Inoltre, tendono a occupare più memoria, perché in pratica stai memorizzando un elenco di cifre.

Dopo che è possibile rappresentare il numero desiderato per il dettaglio desiderato, una soluzione di arrotondamento è semplice. Le probabilità sono che non avrai nemmeno bisogno di una soluzione di arrotondamento; perché, il motivo principale per cui stai cercando di arrotondare in questo caso è dovuto al fatto che il float non è in grado di rappresentare correttamente il tuo valore.

2

È necessario prestare molta attenzione quando si utilizza il punto mobile durante la scrittura del software.
Alcuni numeri decimali non hanno una rappresentazione base esatta 2 è una cosa da tenere a mente. 0.1, 0.01, 0.001 sono alcuni esempi. Quindi per rappresentare questi numeri nella base 2 ha bisogno di arrotondare.

Un altro problema è che si tratta di un insieme finito di bit per rappresentare i numeri e potrebbero verificarsi altri errori di arrotondamento. Inoltre, più ci si allontana da 0, più numeri ci sono che non possono essere esattamente rappresentati, e quindi l'arrotondamento avviene.

ci sono molti altri problemi. La maggior parte sono citati nel documento qui sotto. Per un trattato formale, vedere: http://www.scribd.com/doc/5836/What-Every-Computer-Scientist-Should-Know-About-FloatingPoint-Arithmetic

Non utilizzare galleggianti in cui è necessario conoscere un numero esatto.

1

Come altri nota, float ha sufficiente precisione per contenere il risultato pieno. Il costruttore BigDecimal(double) è esatto, quindi è un modo pratico per vedere la rappresentazione:

System.out.println(new BigDecimal(32000.0001f)); // as float 
System.out.println(new BigDecimal(32000.0001d)); // as double 

che visualizza questo:

32000 
32000.00010000000111176632344722747802734375 
+0

Se si analizzarlo dal testo, è necessario utilizzare il BigDecimal (String) '' costruttore; darà una precisione ancora migliore –

+0

@ Manoan Manoan: corretto; questo è semplicemente un modo conveniente per confrontare le rappresentazioni decimali dei corrispondenti valori 'float' e' double'. Questa calcolatrice è un'alternativa: http://babbage.cs.qc.edu/IEEE-754/Decimal.html – trashgod