2012-03-26 6 views

risposta

27

C'è una cosa importante da notare circa la linea

System.out.print((long)(1 << (63))); 

Per prima cosa prendete (1 << 63), e poi lanci a lunga. Di conseguenza, in realtà stai spostando a sinistra in numeri interi, quindi il cast lungo non ha alcun effetto. Ecco perché lo spostamento di 63 bit a sinistra fornisce il numero intero minimo anziché il valore minimo.

Ma c'è un altro punto, più importante. I long Java sono sempre firmati, quindi anche la riga

System.out.print(1L << 63); 

darebbe un numero negativo. Sotto il complemento a due, ogni volta che il bit più a sinistra è un 1 il numero è negativo.

In realtà non può rappresentare il numero 2 = 9223372036854775808 in un tipo primitivo Java, perché questo numero è più grande della massima lunghezza, ed è la più grande long tipo primitivo. È possibile rappresentare questo numero come BigInteger, tuttavia. È anche possibile generare tramite un sinistra-shift del 63 con il codice

BigInteger.ONE.shiftLeft(63) 
+0

Oh grazie, è davvero chiaro ora –

+0

+1 per un'ottima risposta, che include anche una soluzione pratica. post scriptum Spero non ti dispiaccia che mi sono preso la libertà di modificare 2^63 in qualcosa di più leggibile. – amit

+0

@amit No, non mi dispiace affatto. Grazie! –

6

si stanno avendo un integer overflow [due volte].

1 << 32 == 1 
1 << 31 == -2147483648 [ becuase this is the binary representation in 2's complement for -2147483648] 
1 << 63 == 1 << (32 + 31) == (1 << 32) << 31 == 1 << 31 == -2147483648 

Quando si esegue (long)(1 << (63)) si è solo getto del risultato di 1 << (63) [che è -2147483648] per un long - e non cambia il suo valore.

+0

Grazie per aver segnalato e descritto lo straripamento! Ho cercato una spiegazione a questo codice trovato nell'implementazione BitSet di OpenJDK: [long firstWordMask = WORD_MASK << fromIndex; long lastWordMask = WORD_MASK >>> -toIndex; ] anche se in questo caso WORD_MASK è lungo. – ruizpauker