relacionales operadores desplazamiento asignacion java bit-manipulation byte

desplazamiento - operadores de bits java



manipulaciĆ³n de bits java (5)

byte x = -1; for(int i = 0; i < 8; i++) { x = (byte) (x >>> 1); System.out.println("X: " + x); }

Según tengo entendido, java almacena datos en complemento de dos, lo que significa -1 = 11111111 (según wikipedia).

Además, de los documentos de Java: "El patrón de bits está dado por el operando de la izquierda y el número de posiciones para cambiar por el operando de la derecha. El operador de desplazamiento a la derecha sin signo" >>> "cambia un cero a la izquierda posición, mientras que la posición más a la izquierda después de ">>" depende de la extensión de la señal. "

Lo que significa que >>> desplazaría un 0 al bit más a la izquierda cada vez. Así que espero que este código sea

iteración: representación de bits de x

0: 11111111

1: 01111111

2: 00111111

3: 00011111

...pronto

Sin embargo, mi salida siempre es X: -1, lo que significa (supongo) que >>> está poniendo el bit de signo en la posición más a la izquierda. Entonces intento >> y el mismo resultado.

¿Que esta pasando? Esperaría que mi salida fuera: X: -1, x: 127, x: 63, etc.


No estoy seguro de esto. Pero, creo que es

x >>> 1

se promueve a un int de byte, porque el literal "1" es un int. Entonces, lo que estás observando tiene sentido.


No sé por qué no funciona, pero una manera fácil de borrar el bit superior es & con (binario) 0111111:

x = (byte) (x >>> 1) & 0x7F;


Quien pensó que los bytes deberían ser firmados cuando se inventó Java debe ser sacado y batido con un palo húmedo de apio hasta que lloren :-)

Puedes hacer lo que quieras al enviar a un int y asegurarte de que nunca cambias un 1 al bit superior, algo como esto:

byte x = -1; int x2 = ((int)x) & 0xff; for(int i = 0; i < 8; i++) { x2 = (x2 >>> 1); System.out.println("X: " + x2); }

Su problema particular es porque >>> está lanzando hasta un int para hacer el cambio, luego lo está volviendo a un byte, como se muestra aquí:

byte x = -1; int x2 = ((int)x) & 0xff; int x3; int x4 = x2; for(int i = 0; i < 8; i++) { x2 = (x2 >>> 1); System.out.println("X2: " + x2); x3 = (x >>> 1); x = (byte)x3; x4 = (x4 >>> 1); System.out.println("X: " + x3 + " " + x + " " + x4); }

Qué salidas:

X2: 127 X: 2147483647 -1 127 X2: 63 X: 2147483647 -1 63 X2: 31 X: 2147483647 -1 31 X2: 15 X: 2147483647 -1 15 X2: 7 X: 2147483647 -1 7 X2: 3 X: 2147483647 -1 3 X2: 1 X: 2147483647 -1 1 X2: 0 X: 2147483647 -1 0

Puede ver claramente que x y x3 no funcionan (aunque x3 se desplace correctamente, volviéndolo a byte en x lo ajusta a -1 de nuevo). x4 funciona a la perfección.


Recuerda eso:

  • los operandos de operaciones bit a bit siempre se promueven a al menos un int !
  • los moldes siempre implican extensión de letrero .

Entonces, cuando lo haga (x >>> n), a pesar de que definió x como un byte, a los fines del cambio, primero se convertirá en un int. Si el byte que se convierte es negativo, entonces todos los "bits adicionales" (por lo tanto, los 24 bits más a la izquierda de la int resultante) añadidos para formar un int se establecerán en 1. O dicho de otro modo, si el original el byte fue -1, lo que realmente está cambiando es -1 como un int , es decir, un número de 32 bits con los 32 bits establecidos en 1. Al cambiar este derecho por 1-8 lugares, los 8 bits inferiores se establecerán a 1, por lo tanto, cuando vuelves a un byte, terminas con un byte con los 8 bits establecidos en 1, o en otras palabras, un valor de byte de -1.


El problema es que, como se dijo antes (hace mucho tiempo), x se actualiza a int (sign-extended) antes de realizar el cambio.
Hacer una conversión "bit a bit" debería ayudar:

byte x = -1; for(int i = 0; i < 8; i++) { x = (byte) ((x & 0xFF) >>> 1); System.out.println("X: " + x); }