2009-05-09 20 views
109
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.

Respuesta

149

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.

+5

En realidad, los caracteres no están firmados. – Rollerball

+0

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

+0

¿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. –

22

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.

14

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.

70

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):

  1. 10000100 - 1 = 10000011

  2. 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.

+2

Muy bien explicado – ZAJ

2

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); 

    } 

} 

} 
+0

Nunca he visto eso en ningún libro en 46 años. – EJP

1

aquí es un método muy mecánico sin las teorías de distracción:

  1. convertir el número en una representación binaria (utilizar una calculadora bien?)
  2. copiar sólo los 8 bits de la derecha (LSB) y desechar el resto.
  3. A partir del resultado del paso # 2, si el bit situado más a la izquierda es 0, utilice una calculadora para convertir el número a decimal. Esta es tu respuesta.
  4. Else (si el bit situado más a la izquierda es 1) su respuesta es negativa. Deje todos los ceros a la derecha y el primer bit distinto de cero sin cambios. Y revirtió el resto, es decir, reemplaza 1 por 0 y 0 por 1. Luego use una calculadora para convertir a decimal y añada un signo negativo para indicar que el valor es negativo.

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.

+0

* ¿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

1

Two's complement Equation:

enter image description here


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 
1

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; 
} 
+0

No se puede volver de 'toByte()' si se declara una función 'void' ... –

+0

Solucionado, gracias @JohnPerry –

-1
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   
+0

La respuesta correcta se obtiene mediante el enmascaramiento de bits, no por división y resto. – EJP

0

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++).

+0

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!) –

+0

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

+1

Sí. ¡El cambio de "esencialmente" a "conceptualmente" hace una gran diferencia! –