2015-08-22 17 views
10

Sto cercando di capire il tipo casting in Java. Ho letto che long viene convertito in int utilizzando modulo ridotto per intervallo di int e float viene convertito in int rimuovendo la parte frazionaria. Ho provato il seguente codice.Trasmissione di tipo Java - float (e long) a int

class test 
{ 
    public static void main(String arf[]) 
    { 
     System.out.println((int)2147483648.0); 
     System.out.println((int)2147483648L); 
    } 
} 

... dove 2147483647 è il valore massimo di int.

Il risultato è:

2147483647 
-2147483648 

Quando float viene convertito int sua parte frazionaria viene rimosso. Quindi, (int)2147483648.0 dovrebbe essere uguale a -2147483648.

Qualcuno può spiegarmi perché lo 2147483648.0 viene assegnato a 2147483647?

+2

Non è che in realtà un tipo di doppio? Per utilizzare float è necessario definire il numero 2147483648.0f. – juunas

risposta

8

Non importa quale maggior valore (di int valore massimo) si dà come valore float, taglia (attacchi) verso il basso per int valore massimo che è 2147483647

System.out.println((int)2147483699.0); //2147483647 
System.out.println((int)3147483699.0); //2147483647 

Edit:

La gamma di long in java è -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 (inclusive). dove come -2,147,483,648 and 2,147,483,647 (inclusive).

Quindi se il valore di long è maggiore/minore del valori dati per uno int, la conversione non è mai accurata.

+0

e per quanto tempo? Potresti spiegare per favore. – hermit

+0

@hermit guarda il mio edit –

+2

@downvoter, non mi interessa mai questo -2 rep. Ma per favore commenta, se hai trovato qualcosa di sbagliato in esso. Imparerà. –

3

Il compilatore è lo smartwatch qui. Se osservate attentamente il codice byte, potete vedere che il compilatore sta sostituendo il valore float in Integer.MAX_VALUE.

Così, come Suresh dice, qualsiasi valore float sopra 2147483647,0 è sostituito dal 2147483647.

codice:

public static void main(String arf[]) { 
     int i = (int) 2147483649121.0f; 
     System.out.println(i); 
     System.out.println((int) 2147483648L); 
    } 

codice Byte:

public static void main(java.lang.String[]); 
    flags: ACC_PUBLIC, ACC_STATIC 
    Code: 
     stack=2, locals=2, args_size=1 
     0: ldc   #16     // HERE : int 2147483647 
     2: istore_1  
     3: getstatic  #17     // Field java/lang/System.out:Ljava/io/PrintStream; 
     6: iload_1  
     7: invokevirtual #23     // Method java/io/PrintStream.println:(I)V 
     10: getstatic  #17     // Field java/lang/System.out:Ljava/io/PrintStream; 
     13: ldc   #29     // int -2147483648 
     15: invokevirtual #23     // Method java/io/PrintStream.println:(I)V 
     18: return   
12

2147483648,0 è in realtà 2 , mentre il valore massimo per un int è 2 -1. Quindi, quel valore in virgola mobile è letteralmente un valore troppo alto per adattarsi.

Il motivo per cui verrà troncato al valore int più elevato è descritto come in the language specification come conversione di restringimento.

  1. Nella prima fase, il numero in virgola mobile è convertita in un lungo, se T è lunga, oa un int, se T è byte, short, char, o int, come segue:

    • Se il numero in virgola mobile è NaN (§4.2.3), il risultato della prima fase della conversione è un int long 0.

    • Altrimenti, se il galleggiante il punto-punto non è un infinito, il punto fluttuante il valore viene arrotondato a un valore intero V, arrotondando a verso zero utilizzando la modalità round-to-zero IEEE 754 (§4.2.3). Poi ci sono due casi:

    • Se T è lunga, e questo valore intero può essere rappresentato come un lungo, allora il risultato della prima fase è la lunga valore V.

    • Altrimenti, se questo valore intero può essere rappresentato come un int, allora il risultato della prima fase è il valore int V.

la parte rilevante qui è che il valore sarà rotondo verso lo zero. Fino a quando il valore a virgola mobile (o lungo) è superiore a Integer.MAX_VALUE, un cast a int genererà il valore più alto. Lo stesso vale per un valore inferiore a Integer.MIN_VALUE.

Qualcosa di curioso accade se si utilizza (int)-214783649L; diventerà improvvisamente 214783647! Perché ciò accada è anche spiegato nel JLS, sottolineatura mia:

Una conversione restringimento di un intero con segno a un tipo integrale T scarta semplicemente tutti ma i bit di ordine n bassi, dove n è il numero di bit utilizzato per rappresentare il tipo T. Oltre a una possibile perdita di informazioni sulla grandezza del valore numerico, ciò può causare la differenza del segno del valore risultante dal segno del valore di input.

La lunga rappresentazione di tale valore binario con un tubo che denota il cut-off 32 bit, si presenta come segue:

1111 1111 1111 1111 1111 1111 1111 1111 | 0111 1111 1111 1111 1111 1111 1111 1111 

Quando una conversione avviene, i primi 32 bit sono scartati, lasciando tu con il massimo possibile int.

L'inverso è vero con un positivo lungo - i 32 bit più alti contengono tutti gli 1 che vengono scartati in una conversione.

La struttura integrale è basso, con pipa denota il segno 32 bit:

1111 1111 1111 1111 1111 1111 1111 1111 | 1000 0000 0000 0000 0000 0000 0000 0000 
+3

Non sono stato in grado di trovare una copia di IEEE 754 che non sia molto costosa, ma dubito che IEEE 754 round-to-zero sia la parte importante. Sono abbastanza sicuro che la parte produca ancora '2147483648.0'. La parte importante è subito dopo la parte che hai citato, dove descrive cosa succede se il risultato non è ancora rappresentabile nel tipo T: "Altrimenti, uno dei seguenti due casi deve essere vero: ... Il valore deve essere troppo grande (un ** valore positivo di grande magnitudine ** o infinito positivo), e il risultato del primo passo è il più grande valore rappresentabile di tipo int o long. " – user2357112

+0

L'arrotondamento verso lo zero si applica solo quando è presente una parte frazionaria. Non spiega come l'8 sia diventato 7. – EJP

0

Qualunque numero intero maggiore di 2147483647 causa un overflow.Qualsiasi cessione o la fusione in questi casi produce max negativo int -

aspetto (int) 2147483699L) si produce anche -2147483647

System.out.println((int)2147483699L); 
Problemi correlati