int i =132;
byte b =(byte)i;
System.out.println(b);
La salida es -124¿Cómo convierte Java int en un byte?
¿Por qué? Sé que esta es una pregunta muy básica, pero todavía no puedo mapearla o no entiendo cómo sucede esto.
int i =132;
byte b =(byte)i;
System.out.println(b);
La salida es -124¿Cómo convierte Java int en un byte?
¿Por qué? Sé que esta es una pregunta muy básica, pero todavía no puedo mapearla o no entiendo cómo sucede esto.
En Java, un int
es de 32 bits. A byte
es 8 bits
.
Todo en Java está firmado, y byte
s, int
s, long
s están codificados en complemento a dos.
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.
así que si tienes bytes 255
: 11111111
y que quiere representar como una int
(32 bits) simplemente copia la 1 a la izquierda 24 veces.
Ahora, una forma de leer un número de complemento de dos negativo es comenzar con el bit menos significativo, mover a 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 elimine todo menos los 8 bits menos significativos. (0xff)
Así:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
imprimiría: "Signed: -1 Unsigned: 255"
lo que realmente está pasando aquí?
Estamos utilizando AND a nivel de bits para enmascarar todos los bits de signo extraños (los 1 a la izquierda de los 8 bits menos significativos) Cuando un int se convierte en un byte, Java corta el más a la izquierda bits de
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
desde el bit 32 es ahora el bit de signo en lugar del octavo bit (y nos fijamos el bit de signo a 0, lo que es positivo), el original de 8 bits del byte son leídos por Java como un positivo valor.
bytes en Java está firmado, por lo que tiene un rango -2^7 a 2^7-1 - es decir, -128 a 127. Como 132 está por encima de 127, terminas envolviendo a 132-256 = -124. Es decir, esencialmente 256 (2^8) se suman o restan hasta que caiga dentro del rango. Para obtener más información, puede leer en two's complement.
132 está fuera del rango de un byte que es -128 a 127 (Byte.MIN_VALOR a Byte.MAX_VALUE) En cambio, el bit superior del valor de 8 bits se trata como el firmado que indica que es negativo en este caso. Entonces el número es 132 - 256 = -124.
Para entender cómo funciona, necesitamos saber que las computadoras funcionan en bits.
132 en base 10 (decimal) es 10000100
en base 2 (binario). Desde tiendas de Java int
en 32 bits, lo que tenemos es
00000000_00000000_00000000_10000100
Cuando un int
se convierte en un byte
, Java chuletas-off izquierdo de 24 bits. Lo que obtenemos es 10000100
.
En two's complement, el bit más a la izquierda se utiliza como el signo. Si el bit más a la izquierda es 0
, no se hará nada más.
Si el bit situado más a la izquierda es 1
(como lo tenemos aquí), significa que el número es negativo y que es necesario realizar más trabajo. Para obtener la magnitud, que, menos uno, entonces aplicamos one's complement (solicitar el complemento a uno significa que invertir los bits):
10000100
- 1 = 10000011
Invertir 10000011
= 01111100
01111100
cuando se interpreta como un número decimal, es 124.
Así que tenemos un número negativo con una magnitud de 124, que nos da -124.
Muy bien explicado – ZAJ
a menudo en los libros encontrará la explicación de la conversión de int a byte como realizada por módulo de división. esto no es estrictamente correcto como se muestra abajo lo que realmente sucede es los 24 bits más significativos del valor binario del número int se descartan dejando confusión si el bit más a la izquierda restante se establece que designa el número como negativo
public class castingsample{
public static void main(String args[]){
int i;
byte y;
i = 1024;
for(i = 1024; i > 0; i--){
y = (byte)i;
System.out.print(i + " mod 128 = " + i%128 + " also ");
System.out.println(i + " cast to byte " + " = " + y);
}
}
}
Nunca he visto eso en ningún libro en 46 años. – EJP
aquí es 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 los libros de Java que dicen usar modulo, esto definitivamente es incorrecto ya que los 4 pasos que describí anteriormente definitivamente no son una operación de módulo.
* ¿Qué * Java dice que los libros utilicen 'modulo'? Nunca he visto ningún libro de CS que diga eso en 46 años, y mucho menos en cualquier libro de Java. ¿Qué 'modulo'? No hay operación de módulo en Java. Solo un operador restante. – EJP
En Java, byte
(N = 8) y int
(N = 32) están representados por la 2s-complemento se muestra arriba.
partir de la ecuación, una es negativo para byte
pero positivo para int
.
coef: a7 a6 a5 a4 a3 a2 a1 a0
Binary: 1 0 0 0 0 1 0 0
----------------------------------------------
int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132
byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124
Un algoritmo rápido que simula la forma en que el trabajo es la siguiente:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
Cómo este trabajo? Mire a daixtr respuesta. Una implementación del algoritmo exacto lo descrito en su respuesta es la siguiente:
public static int toByte(int number) {
int tmp = number & 0xff;
if ((tmp & 0x80) == 0x80) {
int bit = 1;
int mask = 0;
for(;;) {
mask |= bit;
if ((tmp & bit) == 0) {
bit <<=1;
continue;
}
int left = tmp & (~mask);
int right = tmp & mask;
left = ~left;
left &= (~mask);
tmp = left | right;
tmp = -(tmp & 0xff);
break;
}
}
return tmp;
}
No se puede volver de 'toByte()' si se declara una función 'void' ... –
Solucionado, gracias @JohnPerry –
N is input number
case 1: 0<=N<=127 answer=N;
case 2: 128<=N<=256 answer=N-256
case 3: N>256
temp1=N/256;
temp2=N-temp*256;
if temp2<=127 then answer=temp2;
else if temp2>=128 then answer=temp2-256;
case 4: negative number input
do same procedure.just change the sign of the solution
La respuesta correcta se obtiene mediante el enmascaramiento de bits, no por división y resto. – EJP
Conceptualmente, se hacen reiteradas sustracciones de 256 a su número, hasta que se encuentra entre -128 y +127 a. Entonces en tu caso, comienzas con 132, luego terminas 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 idiomas este comportamiento no está definido (por ejemplo, C y C++).
Para ser claros, el resultado que obtienes es el mismo * como si * se hubieran repetido las restas. En la práctica, la JVM en realidad no lo hace de esta manera. (¡Sería terriblemente ineficiente!) –
De hecho. Espero que mi segundo párrafo cubra cómo la JVM realmente hace esto. Pero he jugueteado un poco con mi lenguaje. – Bathsheba
Sí. ¡El cambio de "esencialmente" a "conceptualmente" hace una gran diferencia! –
En realidad, los caracteres no están firmados. – Rollerball
bien hecho, la mejor explicación sobre este tema, Wayne! Solo estoy buscando la formalización matemática por qué en una representación de complemento a dos, el bit de signo puede copiarse a la derecha para agregar bits. Es fácil entenderlo pensando en la regla de cómo obtener el valor negativo de un número. es decir: considere todos los bits de derecha a izquierda y escríbalos sin cambios hasta que forme el primer 1. Luego invierta los siguientes bits. Si considero que el bit faltante es 0, es fácil entender que todos van a 1. Pero estaba buscando una explicación más 'matemática'. – AgostinoX
¿Qué pasa aquí? SignedByte & (0xff) 'es que' 0xff' es un literal de interger, por lo que signedByte se promueve a un entero antes de que se realice la operación bit a bit. –