Estoy tratando de entender cómo Java almacena el entero internamente. Sé que todos los enteros primitivos de Java están firmados (¿excepto los cortos?). Eso significa un bit menos disponible en un byte para el número.
Mi pregunta es, ¿todos los números enteros (positivos y negativos) se almacenan como complemento a 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 los 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í nuevamente es que el letrero dice, ambos son números negativos. ¿Es posible que lo esté leyendo o entendiendo mal?
Editar No estoy seguro de que mi pregunta sea confusa. Obligado a aislar la pregunta:
Mi pregunta precisamente: ¿se almacenan los números positivos binary as is
mientras que los números negativos se almacenan como two's complement
?
Algunos dijeron que todos se almacenan en complemento a dos y una respuesta dice que solo los números negativos se almacenan como complemento a dos.
x
yy
son correctos.Respuestas:
Comencemos resumiendo los tipos de datos primitivos de Java:
byte : el tipo de datos Byte es un entero de complemento a dos con signo de 8 bits .
Corto : el tipo de datos corto es un entero de complemento a dos con signo de 16 bits .
int: el tipo de datos Int es un entero de complemento a dos con signo de 32 bits .
long: el tipo de datos Long es un entero de complemento a dos con signo de 64 bits .
float: el tipo de datos Float es un punto flotante IEEE 754 de 32 bits de precisión simple .
double : el tipo de datos doble es un punto flotante IEEE 754 de 64 bits de doble precisión .
booleano: el tipo de datos booleano representa un bit de información .
char: el tipo de datos char es un solo carácter Unicode de 16 bits .
Fuente
Complemento a dos
"El buen ejemplo de wiki es que la relación con el complemento a dos se realiza al observar que 256 = 255 + 1, y (255 - x) es el complemento a uno de x
0000 0111 = 7 el complemento a dos es 1111 1001 = -7
la forma en que funciona es que el MSB (el bit más significativo) recibe un valor negativo, por lo que en el caso anterior
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 a dos de su valor absoluto. El complemento a dos de un número positivo es cuando se usa esta notación como un número negativo.
Fuente
Como recibí algunos puntos por esta respuesta, decidí agregarle 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
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 , ejemplo:
1011 = -3 0011 = +3
Esta representación es más sencilla. Sin embargo, no puede agregar números binarios de la misma manera que agrega números decimales, lo que dificulta la implementación a nivel de hardware. Además, este enfoque utiliza dos patrones binarios para representar 0, 100 ... 0 y 0 .... 0.
2. Complemento de uno
En esta representación, invertimos todos los bits de un número dado para averiguar su complementario. 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 que representan 0. En esta representación, solo tenemos uno (00 ... 0).
Por ejemplo, queremos encontrar la representación binaria negativa de 4 (decimal) usando 4 bits. Primero, convertimos 4 a binario:
4 = 0100
luego invertimos todos los bits
0100 -> 1011
finalmente, agregamos un poco
1011 + 1 = 1100.
Entonces 1100 es equivalente a -4 en decimal si usamos una representación binaria de complemento a 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 como:
0100 -> 1100 ^^ ||-(fixing this value) |--(inverting this one)
La representación del complemento a dos, además de tener una sola representación para el 0, también suma dos valores binarios de la misma forma que en decimal, números pares con diferentes signos. Sin embargo, es necesario verificar los casos de desbordamiento.
4. Sesgo
Esta representación se utiliza para representar el exponente en la norma IEEE 754 para 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 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
fuente
binary as is
mientras que los números -ve se almacenantwo's complement
?Los enteros de Java son de 32 bits y siempre están firmados. Esto significa que el bit más significativo (MSB) funciona como bit de signo. El número entero representado por an
int
no es más que la suma 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 del MSB es negativo (el mayor negativo posible en realidad), por lo que cuando este bit está activado, el número entero (la suma ponderada) se vuelve negativo.
Simulemos 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 números enteros negativos, más bien podemos decir que la representación binaria de números enteros es siempre 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 declararunsigned int x;
. En los enteros sin signo, el peso del MSB es positivo (2^31
) en lugar de negativo. En ese caso, el rango de anunsigned int
es0
to2^32 - 1
, mientras que anint
tiene rango-2^31
to2^31 - 1
.Desde otro punto de vista, si considera el complemento a dos de
x
como~x + 1
(NO x más uno), aquí está la explicación:Para cualquiera
x
,~x
es solo el inverso de bit a bitx
, por lo que siempre quex
tenga un1
-bit,~x
tendrá un0
-bit allí (y viceversa). Entonces, si los suma, no habrá acarreo en la suma y la suma será solo un número entero, cada bit de lo que sea1
.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
1
-bit más a la izquierda simplemente se descartará, porque no cabe en 32 bits (desbordamiento de enteros). Entonces,x + ~x + 1 = 0 -x = ~x + 1
Entonces puede ver que el negativo
x
puede ser representado por~x + 1
, lo que llamamos complemento a dos dex
.fuente
binary as is
mientras que los números -ve se almacenantwo's complement
?He ejecutado el siguiente programa 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
De la salida parece que ha estado usando el complemento a dos.
fuente
11111111 11111111 11111111 11110110
. La suya imprime mientras que Binary tal como está para 10 es 1010. ¿Entonces solo -ve números se almacenan como complemento a dos?Oracle proporciona cierta documentación sobre los tipos de datos Java que puede resultarle interesante. Específicamente:
Por cierto, el corto también se almacena como complemento a dos.
fuente
Según este documento , todos los enteros se firman y almacenan en formato de complemento a dos para java. No estoy seguro de su fiabilidad.
fuente
e.g) 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.
ej.) 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, encontró que MSB está establecido en 1. Por lo tanto, es un no negativo. Y el complemento a 2 se realizará de forma distinta a MSB.
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010 Since MSB representing this is negative 10 --> hence -10 will be retrived.
También tenga en cuenta que cuando está convirtiendo int / short en byte, solo se considerará el último byte junto con el último byte MSB,
Tome el ejemplo "-130" corto, podría almacenarse como se muestra a continuación
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
Ahora la conversión de bytes tomó el último byte, que es 0111 1110. (0-MSB) Dado que MSB dice que es un valor + ve, se tomará como está. Que es 126. (+ ve).
Tome otro ejemplo "130" corto, podría almacenarse como se muestra a continuación
0-000 000 1000 0010 (MSB = 0)
Ahora la conversión de bytes tomó el último byte, que es 1000 0010. (1 = MSB) Dado que MSB dice que es un valor -ve, se realizará el complemento a 2 y se devolverá un número negativo. Entonces, en este caso, se devolverá -126.
1-000 0010 -> (1's complement) -> 1-111 1101 -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110 = -126
(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.
¿Por qué se usa el complemento a dos para representar números negativos?
¿Qué es el "complemento de 2"?
fuente
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 está almacenado en su representación binaria real. pero si es 1, significa que el número es negativo y está almacenado en su representación en complemento a dos. Entonces, cuando le damos peso -2 ^ 32 al bit 32 mientras restauramos el valor entero de su representación binaria, obtenemos la respuesta real.
fuente
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.
fuente
los números positivos se almacenan directamente como binarios. Se requiere el cumplido de 2 para números negativos.
por ejemplo:
15: 00000000 00000000 00000000 00001111-15
: 11111111 11111111 11111111 11110001
aquí está la diferencia en bit con signo.
fuente
Para el entero positivo 2, el valor del complemento es el mismo que el bit 0 de MSB
(like +14 2'complement is 01110)
.Solo para enteros negativos estamos calculando el valor de complemento de 2 '
(-14= 10001+1 = 10010)
.Entonces, la respuesta final es que ambos valores
(+ve and -ve)
se almacenan solo en forma de complemento de 2 '.fuente