2011-09-23 9 views
9

Alcune domande correlate qui.Ragionamento dietro dover specificare L per lungo, F, D per float, doppio

Come per il titolo, perché è un requisito se si specifica il tipo di variabile come lungo o mobile, doppio? Il compilatore non valuta un tipo di variabile al momento della compilazione?

Java considera tutti i letterali integrali come int - è questo per ridurre il rischio di spreco di memoria involontario? E tutti i letterali a virgola mobile come double - per garantire la massima precisione?

risposta

16

Quando si dispone di una costante ci sono sottili differenze tra il valore che sembrano uguali, ma non lo sono. Inoltre, poiché è stata introdotta la funzione di autoboxing, si ottiene un risultato molto diverso quanto meno.

Considera cosa ottieni se si moltiplica 0.1 per 0.1 come float o come double e si converte in float.

float a = (float) (0.1 * 0.1); 
float b = 0.1f * 0.1f; 
System.out.println("a= "+new BigDecimal(a)); 
System.out.println("b= "+new BigDecimal(b)); 
System.out.println("a == b is " + (a == b)); 

stampe

a= 0.00999999977648258209228515625 
b= 0.010000000707805156707763671875 
a == b is false 

Ora confrontare ciò che si ottiene se si utilizza uno o floatint per eseguire un calcolo.

float a = 33333333f - 11111111f; 
float b = 33333333 - 11111111; 
System.out.println("a= "+new BigDecimal(a)); 
System.out.println("b= "+new BigDecimal(b)); 
System.out.println("a == b is " + (a == b)); 

stampe

a= 22222220 
b= 22222222 
a == b is false 

Confronta int e long

long a = 33333333 * 11111111; // overflows 
long b = 33333333L * 11111111L; 
System.out.println("a= "+new BigDecimal(a)); 
System.out.println("b= "+new BigDecimal(b)); 
System.out.println("a == b is " + (a == b)); 

stampe

a= -1846840301 
b= 370370362962963 
a == b is false 

confrontare double con long

double a = 333333333333333333L/333333333L; 
double b = 333333333333333333D/333333333D; 
System.out.println("a= "+new BigDecimal(a)); 
System.out.println("b= "+new BigDecimal(b)); 
System.out.println("a == b is " + (a == b)); 

stampe

a= 1000000001 
b= 1000000000.99999988079071044921875 
a == b is false 

In sintesi sua possibile costruire una situazione in cui utilizzando int, long, double o float produrrà un risultato diverso rispetto all'utilizzo altro tipo.

1

Credo che sia semplicemente per evitare confusione. Come farà il compilatore a sapere che 1.5 è pensato per essere un float o double se non ci sono impostazioni predefinite su cui fare il backup? Per quanto riguarda la valutazione delle variabili, si prega di notare che le variabili! = Letterali.

Modifica 1
Per quanto riguarda alcuni commenti, credo che ci sono momenti in cui non si vorrebbe che il compilatore per tradurre automaticamente letterale sulla destra per tipo di variabile a sinistra.

Edit 2
E naturalmente c'è

public void foo(int bar) { 
    //... 
} 

public void foo(long bar) { 
    //... 
} 

    //... some other method 
    foo(20); // which foo is called? 
+1

sicuro se si passa il letterale a differenza di una variabile tipizzata, ad esempio 'sum (1L, 2L);' - ma perché se sto definendo la variabile con un tipo, ad esempio 'long a = 1 (? L) ; long b = 2 (? L); sum (a, b); '? – wulfgarpro

+0

In un mondo perfetto, il compilatore non sarebbe in grado di capirlo in base al tipo _should_ essere? Naturalmente, questo potrebbe non essere fattibile dato il design di Java, ma non penso che sia impossibile in generale. –

+0

Non so perché chiamano la grammatica "context free", ma almeno coincide con il principio generale che il significato di un'espressione è evidente, non dipendente dal suo contesto. – irreputable

8

Ciò diventa importante quando si fanno più di una semplice assegnazione. Se si prende

float x = 0,1 * 3,0;

fa la differenza se il computer esegue la moltiplicazione in doppia precisione e quindi converte in precisione singola o se prima converte i numeri in precisione singola e quindi moltiplica.

modifica: Non in questo caso esplicito 0.1 e 3.0, ma se i numeri diventano abbastanza complessi, si incontreranno problemi di precisione che mostrano differenze tra virgola mobile e doppia. Rendendolo esplicito al compilatore se si suppone che siano double o float evita l'ambiguità.

Problemi correlati