2014-07-15 10 views
15

Ho provato questa conversione int e long dove ho provato ad assegnare una variabile int a una variabile long. Il codice è il seguente:int to long assignment

public static void main(String []args){ 
    int i = 1024; 
    long j = i; 
    long k = i*i*i*i; 
    System.out.println("j= " +j+ ", k= " +k); 
} 

Così, durante la stampa j, semplicemente ha dato una potenza di 1024. Ma durante la stampa di k, ha mostrato un overflow (k = 0). Ho risolto questo problema utilizzando questa tecnica, dove ho espressamente castato ogni i a long. cioè

public static void main(String []args){ 
    int i = 1024; 
    long j = i; 
    long k = ((long)i)*((long)i)*((long)i)*((long)i); 
    System.out.println("j= " +j+ ", k= " +k); 
} 

Ora, mostravano valori corretti sia j e k. Quindi, volevo sapere perché è necessario trasmettere int nel secondo caso ma non nel primo. k, essendo un long può mantenere questo valore dopo questa pesante assegnazione. Ma perché non è stato assegnato correttamente?

+0

il primo casting 'i' a long dovrebbe essere sufficiente –

+0

((long) i) * i * i * i –

+4

Il pattern difettoso che hai identificato - una moltiplicazione di numeri interi che potrebbero traboccare che viene convertita" troppo tardi "in un tipo più grande - è relativamente comune sia in C# che in Java; troviamo più di cinque istanze per milione di righe di codice analizzate. Un difetto correlato con un tasso di scoperta simile è una divisione di due interi e una conversione "troppo tardi" in un doppio; la gente è spesso sorpresa che trecento divisi per cinquecento e assegnati a un doppio sia zero, non 0,6. –

risposta

19

Il motivo è che la vostra linea

long k = i*i*i*i; 

può essere pensato come

long k = ((i*i)*i)*i; 

o ...

int k1 = i*i; 
int k2 = k1*i; 
int k3 = k2*i; 
long k = k3; 

Così, quando una delle kn overflow, si ottiene il errore.

Quando si esegue il cast, si aggirano ovviamente questo problema moltiplicando sempre i long s.

Naturalmente la modifica più semplice al programma iniziale è definire immediatamente come long, anziché int.

long i = 1024L; 
+0

@dav_i, 'k3' sarà overflow perché è la variabile' int', deve essere 'lunga' – MajidTaheri

6

i*i*i*i è un all int moltiplicazione quindi la risultante è intero solo (che trabocca nel caso). per lungo risultante è sufficiente convertire uno di loro a lungo e quindi questo è sufficiente

long k = ((long)i)*i*i*i; 
+0

L'associatività entra in gioco qui? Intendevo, se è giusto associativo, quindi, se attraversa il valore integer_max_value prima di arrivare alla (lunga i), nel tuo caso mostrerà di nuovo un trabocco. –

+0

provalo @ShashishChandra – Sanjeev

+1

L'ho provato, e grazie a te ha funzionato. Stavo solo chiedendo, c'è qualche ruolo di associatività qui? –

2

Nel primo il valore di i è un int e il multipllication intero accadendo e i*i*i*i risultato è intero e quindi la integer overflow.

Dove come nel secondo caso si sta dicendo esplicitamente/facendo il risultato come long.

+0

Grazie per la risposta. È davvero utile Apprezzalo. –

2

1099511627776 che è il risultato della moltiplicazione è >Integer.MAX_VALUE come è integer Moltiplicazione così dopo i*i*i valore sarebbe 1073741824 ma dopo la moltiplicazione con 1024 diventa fuori portata che provoca integer overflow e k sarà 0.

  • Si può lanciare uno dei i-long
  • Moltiplica con 1L (1L*i*i*i*i), ma non i*i*i*i*1L
  • È inoltre possibile assegnare i*i*i a lungo e di moltiplicarsi con i come questo long k =(k=i*i*i)*i;
+1

Grazie per la risposta. Lo apprezzo. –

7

Questo problema si basa sul fatto che i tipi diversi di utilizzano diverse quantità di memoria. int e long sono entrambi numeri interi, la differenza è che int è 4 byte, mentre lungo è 8 byte.

Lets modificare il codice un po ':

public class Test { 


    public static void main(String []args){ 
     int i = 1024; 
     long j = i; 
     long k = i*i*i; 

     System.out.println("My multipliers are of type int:"); 
     System.out.println("j= " +j+ ", k= " +k);   
     System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO")); 
     k = i*i*i*i; 
     System.out.println("j= " +j+ ", k= " +k); 

     //now multiplying with j instead of i 
     System.out.println("\nNow Im working with a long type:"); 
     k = j*j*j; 
     System.out.println("j= " +j+ ", k= " +k);   
     System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO")); 
     k = j*j*j*j; 
     System.out.println("j= " +j+ ", k= " +k); 
     System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO")); 
     k = j*j*j*j; 

    } 

} 

Il codice sopra mostra che quando si ho moltiplicato per 3 volte il risultato è un valore che è più piccolo di Integer.MAX_VALUE (che è 2147483647), e quando stai moltiplicando 4 volte il risultato è 0 poiché non c'è abbastanza posto nei poveri 4 byte dei moltiplicatori. :) Ma si può vedere che quando i moltiplicatori (lato destro, j) sono di tipo lungo, viene stampato il valore corretto e l'ultima stampa mostra che l'istruzione k < Integer.MAX_VALUE è falsa, che è la ragione del tuo zero. :)

+0

Grazie per la risposta. Lo apprezzo. –