2011-08-16 9 views
6

Ho appena appreso da Peter Lawreys post che questa è un'espressione valida e restituisce true.Perché è consentita la precisione arbitraria nei doppi letterali in Java?

333333333333333.33d == 333333333333333.3d 

La mia domanda è, perché è permesso di avere doppi letterali, che non possono essere rappresentati in un doppio, mentre letterali interi che non possono essere rappresentati non sono consentite. Qual è la motivazione per questa decisione.


Una nota a margine, ho può effettivamente innescare fuori errore di compilazione gamma di doppie letterali :-)

99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999d 

Quindi, fintanto che siamo in (min, max) gamma, il letterale viene approssimato, ma quando si esce da questo, sembra che il compilatore si rifiuti di approssimarlo.

+5

Come stai proponendo, possiamo facilmente rappresentare il doppio che è "il più vicino possibile a 0,1" se disattivi 0,1? –

+0

Buon punto. Che ovvio ...: P – aioobe

risposta

9

Il problema è che pochissimi decimali che è possibile digitare possono essere rappresentati esattamente come un float IEEE. Quindi, se rimuovevi tutte le costanti non esatte, faresti uso di letterali doppi molto ingombranti. Il più delle volte il comportamento di "fingere di poterlo rappresentare" è molto più utile.

+0

Buon punto! Che ovvio! Grazie per segnalarlo. – aioobe

+0

Le rappresentazioni non sono uniformemente distanziate tra -MAX e MAX, quindi la rappresentazione del "miglior sforzo" è * molto * migliore per alcuni rispetto ad altri. L'esempio che hai mostrato sembra essere piuttosto cattivo. – Flexo

2

Il motivo principale è probabilmente che Java non è in grado di dire quando si sta esaurendo la precisione perché non esiste un codice op CPU per quello.

Perché non c'è alcun flag CPU o simile? Perché la rappresentazione del numero semplicemente non lo consente. Ad esempio anche numeri semplici come "0.1" non hanno una rappresentazione definita. 0.1 ti dà "00111111 10111001 10011001 10011001 10011001 10011001 10011001 10011010" (vedi http://www.binaryconvert.com/result_double.html?decimal=048046049).

Tale valore non è esattamente 0,1 ma 1.00000000000000005551115123126E-1.

Quindi, anche per questi casi "semplici", il codice dovrebbe generare un'eccezione.

+2

È possibile calcolare se un decimale è esattamente rappresentabile anche se penso, senza la necessità di codici op. CPU. – Flexo

+0

Vero ma sarebbe terribilmente lento. Allora, qual è il tuo punto? –

Problemi correlati