¿Cómo se representan internamente los enteros en un nivel de bit en Java?

Estoy tratando de entender cómo Java almacena enteros internamente. Sé que todos los enteros primitivos de java están firmados (¿excepto el corto?). Eso significa un bit menos disponible en un byte para el número.

Mi pregunta es, ¿están todos los enteros (positivos y negativos) almacenados como complemento de dos o solo son números negativos en complemento a dos?

Veo que las especificaciones dicen x bit two's complement number . Pero a menudo me confundo.

Por ejemplo:

  int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111? int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010 

Editar

Para ser claro, x = 15

  In binary as is: `00000000 00000000 00000000 00001111' Two's complement: `11111111 11111111 11111111 11110001` 

Entonces, si su respuesta es que all números se almacenan como complemento a dos, entonces:

  int x = 15; // 11111111 11111111 11111111 11110001 int y = -22 // 11111111 11111111 11111111 11101010 

La confusión aquí otra vez es que el signo dice que ambos son números negativos. ¿Puedo estar malinterpretando / malentendiéndolo?

Editar No estoy seguro de que mi pregunta sea confusa. Obligado a aislar la pregunta:

Mi pregunta es precisa: ¿Se almacenan los números positivos en binary as is mientras que los números negativos se almacenan como two's complement ?

Algunos dijeron que todos están almacenados en el complemento de dos y una respuesta dice que solo los números negativos se almacenan como complemento de dos.

Comencemos por resumir los tipos de datos primitivos de Java:

byte : el tipo de datos Byte es un entero de complemento de dos firmado de 8 bits.

Corto : tipo de datos cortos es un entero complementario de dos firmado de 16 bits.

int: tipo de datos Int es un entero de complemento de dos firmado de 32 bits.

long: Long data type es un entero de complemento de dos firmado de 64 bits.

flotante: el tipo de datos flotantes es un punto flotante IEEE 754 de precisión simple de 32 bits .

double : double data type es un punto flotante IEEE 754 de 64 bits de doble precisión.

boolean: el tipo de datos booleano representa un bit de información .

El tipo de datos char: char es un único carácter Unicode de 16 bits .

Fuente

Complemento de dos

“El buen ejemplo es del wiki que la relación con el complemento a dos se realiza al notar que 256 = 255 + 1 y (255 – x) es el complemento de x

0000 0111 = 7 complemento de dos es 1111 1001 = -7

la forma en que funciona es el msb (bit más significativo) recibe un valor negativo, por lo que en el caso anterior

-7 = 1001 = -8 + 0+ 0+ 1

Los enteros positivos generalmente se almacenan como números binarios simples (1 es 1, 10 es 2, 11 es 3 y así sucesivamente).

Los enteros negativos se almacenan como el complemento de dos de su valor absoluto. El complemento de dos de un número positivo es, al usar esta notación, un número negativo.

Fuente

Como recibí algunos puntos para esta respuesta, decidí agregar más información.

Una respuesta más detallada:

Entre otros, hay cuatro enfoques principales para representar números positivos y negativos en binario, a saber:

  1. Magnitud firmada
  2. El complemento de uno
  3. Complemento de dos
  4. Parcialidad

1. Magnitud firmada

Utiliza el bit más significativo para representar el signo, los bits restantes se utilizan para representar el valor absoluto. Donde 0 representa un número positivo y 1 representa un número negativo , por ejemplo:

 1011 = -3 0011 = +3 

Esta representación es más simple. Sin embargo, no puede agregar números binarios de la misma manera que agrega números decimales, lo que dificulta su implementación en el nivel de hardware. Además, este enfoque usa dos patrones binarios para representar el 0, 100 … 0 y 0 …. 0.

2. El complemento uno

En esta representación, invertimos todos los bits de un número dado para descubrir su complementariedad. Por ejemplo:

 010 = 2, so -2 = 101 (inverting all bits). 

El problema de esta representación es que todavía existen dos patrones de bits para representar el 0 (00..0 y 11..1)

3. Complemento de dos

Para encontrar el negativo de un número, en esta representación, invertimos todos los bits y luego agregamos un bit. Agregar un bit resuelve el problema de tener dos patrones de bits representando 0. En esta representación, solo tenemos uno (00 … 0).

Por ejemplo, queremos encontrar la representación negativa binaria de 4 (decimal) usando 4 bits. Primero convertimos 4 a binario:

 4 = 0100 

luego invertimos todos los bits

 0100 -> 1011 

finalmente agregamos un bit

 1011 + 1 = 1100. 

Entonces 1100 es equivalente a -4 en decimal, si estamos usando una representación binaria Complemento de dos con 4 bits.

Una forma más rápida de encontrar el complementario es fijando el primer bit como valor 1 e invirtiendo los bits restantes. En el ejemplo anterior, sería algo así como:

 0100 -> 1100 ^^ ||-(fixing this value) |--(inverting this one) 

La representación Complemento dos, además de tener solo una representación para 0, también agrega dos valores binarios de la misma manera que en los números decimales, pares y con signos diferentes. Sin embargo, es necesario verificar si hay casos de desbordamiento.

4. Sesgo

Esta representación se usa para representar el exponente en la norma IEEE 754 para los puntos flotantes. Tiene la ventaja de que el valor binario con todos los bits a cero representa el valor más pequeño. Y el valor binario con todos los bits a 1 representa el valor más grande. Como su nombre indica, el valor está codificado (positivo o negativo) en binario con n bits con un sesgo (normalmente 2 ^ (n-1) o 2 ^ (n-1) -1).

Entonces, si estamos usando 8 bits, el valor 1 en decimal se representa en binario usando un sesgo de 2 ^ (n-1), por el valor:

 +1 + bias = +1 + 2^(8-1) = 1 + 128 = 129 converting to binary 1000 0001 

Los enteros de Java son de 32 bits y siempre están firmados. Esto significa que el bit más significativo (MSB) funciona como el bit de signo. El entero representado por un int no es más que la sum ponderada de los bits. Los pesos se asignan de la siguiente manera:

 Bit# Weight 31 -2^31 30 2^30 29 2^29 ... ... 2 2^2 1 2^1 0 2^0 

Tenga en cuenta que el peso de la MSB es negativo (el mayor negativo posible en realidad), de modo que cuando este bit está activado, el número entero (la sum ponderada) se vuelve negativo.

Simularlo con números de 4 bits:

 Binary Weighted sum Integer value 0000 0 + 0 + 0 + 0 0 0001 0 + 0 + 0 + 2^0 1 0010 0 + 0 + 2^1 + 0 2 0011 0 + 0 + 2^1 + 2^0 3 0100 0 + 2^2 + 0 + 0 4 0101 0 + 2^2 + 0 + 2^0 5 0110 0 + 2^2 + 2^1 + 0 6 0111 0 + 2^2 + 2^1 + 2^0 7 -> the most positive value 1000 -2^3 + 0 + 0 + 0 -8 -> the most negative value 1001 -2^3 + 0 + 0 + 2^0 -7 1010 -2^3 + 0 + 2^1 + 0 -6 1011 -2^3 + 0 + 2^1 + 2^0 -5 1100 -2^3 + 2^2 + 0 + 0 -4 1101 -2^3 + 2^2 + 0 + 2^0 -3 1110 -2^3 + 2^2 + 2^1 + 0 -2 1111 -2^3 + 2^2 + 2^1 + 2^0 -1 

Entonces, el complemento a dos no es un esquema exclusivo para representar enteros negativos, sino que podemos decir que la representación binaria de los enteros siempre es la misma, simplemente negamos el peso del bit más significativo. Y ese bit determina el signo del número entero.

En C, hay una palabra clave unsigned (no disponible en java), que se puede usar para declarar unsigned int x; . En los enteros sin signo, el peso del MSB es positivo ( 2^31 ) en lugar de ser negativo. En ese caso, el rango de un unsigned int es de 0 a 2^32 - 1 , mientras que un int tiene un rango de -2^31 a 2^31 - 1 .

Desde otro punto de vista, si consideramos el complemento a dos de x como ~x + 1 (NO x más uno), aquí está la explicación:

Para cualquier x , ~x es solo la inversa bit a bit de x , entonces dondequiera que x tenga un bit de 1 , ~x tendrá un bit de 0 allí (y viceversa). Entonces, si sum esto, no habrá carry en la sum y la sum será solo un entero, cada bit de los cuales es 1 .

Para enteros de 32 bits:

 x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111 x + ~x + 1 = 1111 1111 1111 1111 1111 1111 1111 1111 + 1 = 1 0000 0000 0000 0000 0000 0000 0000 0000 

El 1bit más a la izquierda simplemente se descartará, porque no cabe en 32 bits (desbordamiento de enteros). Asi que,

 x + ~x + 1 = 0 -x = ~x + 1 

Entonces puedes ver que la x negativa se puede representar por ~x + 1 , que llamamos el complemento de dos de x .

He ejecutado el siguiente progtwig para saberlo

 public class Negative { public static void main(String[] args) { int i =10; int j = -10; System.out.println(Integer.toBinaryString(i)); System.out.println(Integer.toBinaryString(j)); } } 

La salida es

 1010 11111111111111111111111111110110 

Desde la salida, parece que ha estado usando el complemento de dos.

Oracle proporciona cierta documentación con respecto a los tipos de datos Java que puede encontrar interesantes. Específicamente:

int: el tipo de datos int es un entero de complemento de dos firmado de 32 bits. Tiene un valor mínimo de -2,147,483,648 y un valor máximo de 2,147,483,647 (inclusive).

Por cierto, corto también se almacena como complemento de dos.

De acuerdo con este documento , todos los enteros se firman y almacenan en formato de complemento de dos para java. No estoy seguro de su fiabilidad …

El bit más significativo (32º) indica que el número es positivo o negativo. Si es 0, significa que el número es positivo y se almacena en su representación binaria real. pero si es 1, significa que el número es negativo y se almacena en la representación complementaria de los dos. Entonces, cuando damos peso -2 ^ 32 al 32 ° bit mientras restauramos el valor entero de su representación binaria, obtenemos la respuesta real.

Gracias, dreamcrash por la respuesta https://stackoverflow.com/a/13422442/1065835 ; en la página wiki dan un ejemplo que me ayudó a entender cómo encontrar la representación binaria de la contraparte negativa de un número positivo.

Por ejemplo, usando 1 byte (= 2 nibbles = 8 bits), el número decimal 5 está representado por

0000 01012 El bit más significativo es 0, por lo que el patrón representa un valor no negativo. Para convertir a -5 en notación de complemento de dos, los bits están invertidos; 0 se convierte en 1 y 1 se convierte en 0:

1111 1010 En este punto, el número es el complemento de los valores decimales -5. Para obtener el complemento a dos, se agrega 1 al resultado, lo que da:

1111 1011 El resultado es un número binario con signo que representa el valor decimal -5 en forma de complemento a dos. El bit más significativo es 1, por lo que el valor representado es negativo.

Los números positivos se almacenan / recuperan tal como están.

 eg) For +ve number 10; byte representation will be like 0-000 0010 (0 - MSB will represent that it is +ve). So while retrieving based on MSB; it says it is +ve, so the value will be taken as it is. 

Pero los números negativos se almacenarán después del complemento a 2 (que no sea el bit MSB), y el bit MSB se establecerá en 1.

por ejemplo) al almacenar -10 entonces

  0-000 0010 -> (1's complement) -> 0-111 1101 -> (2's complement) 0-111 1101 + 1 -> 0-111 1110 Now MSB will be set to one, since it is negative no -> 1-111 1110 

al recuperar, descubrió que MSB está establecido en 1. Entonces es negativo no. Y el complemento de 2 se realizará aparte de MSB.

  1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010 Since MSB representing this is negative 10 --> hence -10 will be retrived. 

Fundición

También tenga en cuenta que cuando está lanzando int / short to byte, solo el último byte será considerado junto con el último byte MSB,

Tome el ejemplo “-130” corto, podría almacenarse como a continuación

 (MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110 

Ahora el byte fundido tomó el último byte, que es 0111 1110. (0-MSB) Dado que MSB dice que tiene un valor de + ve, se tomará tal como está. Que es 126. (+ ve).

Tome otro ejemplo “130” corto, podría almacenarse como a continuación

  0-000 000 1000 0010 (MSB = 0) 

Ahora el byte fundido tomó el último byte, que es 1000 0010. (1 = MSB) Dado que MSB dice que es -ve value, se realizará el complemento de 2 y se devolverá el número negativo. Entonces, en este caso, se devolverán 126.

  1-000 0010 -> (1's complement) -> 1-111 1101 -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110 = -126 

Diff entre (int) (char) (byte) -1 AND (int) (short) (byte) -1

 (byte)-1 -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111 (char)(byte)-1 -> 1-111 1111 1111 1111 (sign bit is carry forwarded on left) 

similar

 (short)(byte)-1-> 1-111 1111 1111 1111 (sign bit is carry forwarded on left) 

Pero

 (int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111 = 65535 since char is unsigned; MSB won't be carry forwarded. 

Y

 (int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1 since short is signed; MSB is be carry forwarded. 

Referencias

¿Por qué el complemento de dos se usa para representar números negativos?

¿Qué es el “Complemento 2”?

los números positivos se almacenan directamente como binarios. El cumplido de 2 es obligatorio para los números negativos.

por ejemplo:

15: 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001

aquí está la diferencia en el bit firmado.

Para el entero positivo 2, el valor de compleción es el mismo con el bit 0 de MSB (like +14 2'complement is 01110) .

Solo para enteros negativos solo estamos calculando el valor de complemento de 2 ‘ (-14= 10001+1 = 10010) .

Entonces, la respuesta final es que los valores (+ve and -ve) se almacenan solo en forma de 2 ‘.

Intereting Posts