2012-03-26 11 views

Respuesta

27

Hay una cosa importante a tener en cuenta sobre la línea

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

primero tomar (1 << 63), y luego que lances a tiempo. Como resultado, en realidad cambias a la izquierda en números enteros, por lo que el lanzamiento largo no tiene ningún efecto. Es por eso que desplazar 63 bits a la izquierda da el entero mínimo en lugar del minuto mínimo.

Pero hay otro punto más importante. Java longs siempre se firman, por lo que incluso la línea

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

daría un número negativo. En el complemento a dos, cuando el bit más a la izquierda es un 1, el número es negativo.

En realidad no puede representar el número 2 = 9223372036854775808 en un tipo primitivo de Java, porque ese número es más grande que el máximo de longitud, y long es el mayor tipo primitivo. Sin embargo, puede representar este número como BigInteger. Incluso puede generarla a través de una tecla de cambio izquierdo en un 63 con el código

BigInteger.ONE.shiftLeft(63) 
+0

Oh, gracias, está muy claro ahora –

+0

+1 para una excelente respuesta, que también incluye una solución práctica. PD. Espero que no te importe que me tome la libertad de editar 2^63 en algo más legible. – amit

+0

@amit No, no me importa en absoluto. ¡Gracias! –

6

que está teniendo una integer overflow [dos veces].

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 

Al hacer (long)(1 << (63)) Sólo se le haya emitido el resultado de 1 << (63) [que es -2147483648] a un long - y no cambia su valor.

+0

¡Gracias por señalar y describir el desbordamiento! He estado buscando una explicación para este código que se encuentra en la implementación de BitSet de OpenJDK: [long firstWordMask = WORD_MASK << fromIndex; long lastWordMask = WORD_MASK >>> -toIndex; ] aunque en este caso WORD_MASK es largo. – ruizpauker

Cuestiones relacionadas