int i =132;
byte b =(byte)i; System.out.println(b);
Alucinante. ¿Por qué es la salida -124
?
En Java, un int
es de 32 bits. A byte
es 8 bits
.
Se firman la mayoría de los tipos primitivos de Java, y byte
, short
, int
, y long
están codificados en complemento a dos. (El char
tipo no está firmado y el concepto de signo no es aplicable a boolean
).
En este esquema de números, el bit más significativo especifica el signo del número. Si se necesitan más bits, el bit más significativo ("MSB") simplemente se copia al nuevo MSB.
Entonces, si tiene un byte 255
: 11111111
y desea representarlo como un int
(32 bits), simplemente copie el 1 a la izquierda 24 veces.
Ahora, una forma de leer un número de complemento negativo de dos es comenzar con el bit menos significativo, moverse hacia la izquierda hasta encontrar el primer 1, luego invertir cada bit después. El número resultante es la versión positiva de ese número.
Por ejemplo: 11111111
va a 00000001
= -1
. Esto es lo que Java mostrará como el valor.
Lo que probablemente quiera hacer es conocer el valor sin signo del byte.
Puede lograr esto con una máscara de bits que elimina todo menos los 8 bits menos significativos. (0xff)
Entonces:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Imprimiría: "Signed: -1 Unsigned: 255"
¿Qué está pasando realmente aquí?
Estamos utilizando AND a nivel de bits para enmascarar todos los bits de signos extraños (los 1 a la izquierda de los 8 bits menos significativos). Cuando un int se convierte en un byte, Java corta los 24 bits más a la izquierda
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Dado que el bit 32 ahora es el bit de signo en lugar del bit 8 (y establecemos el bit de signo en 0, que es positivo), Java lee los 8 bits originales del byte como un valor positivo.
signedByte & (0xff)
que0xff
está sucediendo aquí es que es un literal entero, por lo queignedByte se promociona a un entero antes de que se realice la operación bit a bit.132
en dígitos ( base 10 ) está1000_0100
en bits ( base 2 ) y Java almacenaint
en 32 bits:El algoritmo para int-by-byte es truncado a la izquierda; Algoritmo para
System.out.println
es el complemento a dos (el complemento a dos es si el bit más a la izquierda es1
, interpretar como complemento a uno negativo (bits invertidos) menos uno); AsíSystem.out.println(int-to-byte(
))
es:0000_0000_0000_0000_0000_0000_1000_0100
) [)))])1000_0100
[)))])1000_0100
))))1000_0011
)))0111_1100
))fuente
0
para positivo y1
para negativo).int
a abyte
es una conversión con pérdida (es decir, se pierde información). Por lo tanto, no hay forma de convertirlo nuevamente a suint
valor original .el byte en Java está firmado, por lo que tiene un rango de -2 ^ 7 a 2 ^ 7-1, es decir, -128 a 127. Dado que 132 está por encima de 127, terminas ajustando a 132-256 = -124. Es decir, esencialmente 256 (2 ^ 8) se suman o restan hasta que caen dentro del rango.
Para obtener más información, es posible que desee leer sobre el complemento de dos .
fuente
132 está fuera del rango de un byte que es -128 a 127 (Byte.MIN_VALUE a Byte.MAX_VALUE) En cambio, el bit superior del valor de 8 bits se trata como el signo que indica que es negativo en este caso. Entonces el número es 132-256 = -124.
fuente
Aquí hay un método muy mecánico sin las teorías de distracción:
Este método más práctico está de acuerdo con las respuestas teóricas anteriores. Entonces, aquellos que todavía leen esos libros de Java que dicen usar el módulo, esto definitivamente es incorrecto ya que los 4 pasos que describí anteriormente definitivamente no son una operación de módulo.
fuente
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdf
página 59Ecuación del complemento a dos:
En Java,
byte
(N = 8) yint
(N = 32) están representados por el complemento 2s que se muestra arriba.De la ecuación, un 7 es negativo para
byte
pero positivo paraint
.fuente
a menudo en los libros encontrará la explicación de la conversión de int a byte como realizada por división de módulo. esto no es estrictamente correcto, como se muestra a continuación, lo que realmente sucede es que los 24 bits más significativos del valor binario del número int se descartan, dejando confusión si se establece el bit que queda más a la izquierda, que designa el número como negativo
fuente
Un algoritmo rápido que simula la forma en que funciona es el siguiente:
¿Cómo funciona esto? Mira a la respuesta daixtr . Una implementación del algoritmo exacto descrito en su respuesta es la siguiente:
fuente
Si quieres entender esto matemáticamente, como cómo funciona
así que, básicamente, los números b / w -128 a 127 se escribirán igual que su valor decimal, por encima de eso (su número - 256).
p.ej. 132, la respuesta será 132 - 256 = - 124 es decir
256 + tu respuesta en el número 256 + (-124) es 132
Otro ejemplo
la salida será 39 44
(295 - 256) (300 - 256)
NOTA: no considerará números después del decimal.
fuente
Conceptualmente, se hacen restas repetidas de 256 a su número, hasta que esté en el rango de -128 a +127. Entonces, en su caso, comienza con 132, luego termina con -124 en un solo paso.
Computacionalmente, esto corresponde a extraer los 8 bits menos significativos de su número original. (Y tenga en cuenta que el bit más significativo de estos 8 se convierte en el bit de signo).
Tenga en cuenta que en otros lenguajes este comportamiento no está definido (por ejemplo, C y C ++).
fuente
fuente