Estoy reescribiendo mi respuesta porque el problema es más sutil de lo que había pensado originalmente. Dejo mi respuesta original a continuación porque es interesante (al menos para mí) pero no es la respuesta correcta a la pregunta.
La pregunta es realmente sobre las reglas de extensión de tipo de Java. Los operadores >> y >>> toman int
s, no byte
sy los valores dados al operador se extienden a int
s antes de la operación.
Entonces, en la computación c, el byte
b se extiende a un int
. Ese aumento de tamaño es una operación firmada, entonces (byte) 0xf1 == (int) 0xfffffff1. El valor de c es 0xfffffff1 >> 4 == 0xffffffff == -1.
El cálculo de d es confuso. De nuevo, b es un signo extendido a 0xfffffff1. El turno sin signo produce 0x00ffffff. Pero la conversión de nuevo a un byte
produce 0xff == -1 nuevamente. Eso no es lo que esperarías si la operación se hiciera realmente en el byte
, pero no lo es.
- Tengo un sitio web estático. Necesito un complemento ligero de CMS para actualizar el sitio. Actualmente uso un recurso HTML a tiempo parcial y es doloroso. ¿Cuál es el mejor CMS desde una perspectiva de usabilidad?
- Estoy escribiendo un libro que depende de la propagación de una enfermedad a través de las avispas. Necesito elegir el correcto para ser el ‘infector’. ¿Puedo obtener ayuda?
- Soy una mujer transgénero y aún no he recibido ningún tratamiento. Tengo miedo de que mi cuerpo no salga como yo quiero. ¿Cómo puede superar este miedo?
- Tengo dos meses de vacaciones en Bangalore. ¿Cómo puedo hacer que estos 2 meses sean fructíferos?
- Completé mi primer año de uno de los mejores gobiernos. universidades en kerala en ECE. Este año obtuve la admisión en BITS Hydrebad para EEE. ¿Qué es mejor, unirme a BITS y gastar 1 año adicional o permanecer en GEC? .Por favor ayuda
Para obtener lo que desea, debe tratar a la fuerza el int
para eliminar la extensión del signo. Lo obtienes por bitx 0xff, que es un número entero igual a 0x000000ff. Entonces b & 0xff = 0x000000f1, y b & 0xff >> 4 == 0x0000000f = 15.
Esto es desagradable, y otra razón más para que los programadores no jueguen tratando de exprimir cosas en valores de byte
individuales. Este es el tipo de cosa que te morderá cada vez.
———————————————————————-
Interesante pero menos relevante digresión original en operadores de turno, en términos aritméticos en lugar de Java:
Los operadores de desplazamiento a la derecha >> y >>> trabajan en bits. Es fácil ir y venir entre binario y hexadecimal, ya que cada dígito hexadecimal se traduce en 4 bits. Entonces:
0xf1 == 1111 0001
desde hexadecimal F = 15 decimal = 1111 binario, y 1 es 0001 binario.
Desplazar a la derecha por 1 mueve todos los bits por 1:
0xf1 >>> 1 == _111 1001 binario = 0x79
El _ es un poco que he dejado fuera; Volveré a eso en un segundo. Cambiar por 4 significa cortar exactamente 1 dígito hexadecimal:
0xf1 >>> 4 == ____ 1111 binario = 0xf hexadecimal
En realidad, hay dos operadores de desplazamiento a la derecha diferentes: con signo (>>) y sin signo (>>>). La diferencia está en lo que va en el _. Para el operador firmado, repite lo que haya allí. Para el operador sin signo, pone a cero:
0xf1 >>> 4 == 0000 1111 binario == 0x0f
0xf1 >> 4 == 1111 1111 binario == 0xff == -1 decimal
El -1 puede parecer un poco sorprendente, pero la forma en que Java interpreta los números a 1 en el bit más a la izquierda significa un número negativo. (Esto se llama “complemento de dos, y dejaré los detalles para otra pregunta.” Desplazarse a la derecha por un lugar puede interpretarse como dividir por 2, siempre que conserve el signo. Entonces:
0xf1 = 1111 0001 = -15 decimal
0xf1 >> 1 == 1111 1000 = -8 decimal
0xf1 >> 2 == 1111 1100 = -4 decimal
0xf1 >> 3 == 1111 1110 = -2 decimal
0xf1 >> 4 = = 1111 1111 = -1 decimal
Tenga en cuenta que esto funciona solo mientras 0xf1 se interprete como un byte. Si dejara la conversión a un byte, se interpretaría como un entero: 0x000000f1, y el bit más a la izquierda sería 0 en lugar de 1.
Si quieres firmar o no firmar es una cuestión de por qué estás haciendo el turno. Si desea la división por potencias de dos, trabajando en números negativos, trabaje con >>. Si solo desea manipular los bits y prefiere que los bits se desplacen a cero, use >>>.
(Nota: todo esto es algo esotérico y ya no es tan importante. No use >> 1 para dividir entre dos: no es más rápido y hace que su código sea confuso. Esa es una resaca de The Good Old Days , cuando los compiladores no se optimizaron tan bien como lo hacen hoy. Hoy, este ejercicio trata más sobre la enseñanza de la aritmética bit a bit de los estudiantes de CS; en realidad no es una cuestión práctica. Las operaciones bit a bit todavía se realizan para las banderas, que deben hacerse sin firmar de hecho, probablemente no debería hacerse con tanta frecuencia como se hace).