Comment les entiers sont-ils représentés en interne au niveau bit en Java?

J’essaie de comprendre comment Java stocke un entier en interne. Je sais que tous les entiers primitifs Java sont signés (sauf les courts?). Cela signifie un bit de moins disponible dans un octet pour le nombre.

Ma question est la suivante: tous les nombres entiers (positifs et négatifs) sont-ils stockés en complément à deux ou ne sont-ils que des nombres négatifs en complément à deux?

Je vois que les spécifications indiquent x bit two's complement number . Mais je suis souvent confus.

Par exemple:

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

modifier

Pour être clair, x = 15

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

Donc, si votre réponse est que all nombres sont stockés en complément à deux, alors:

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

La confusion est là encore le signe dit, les deux sont des nombres négatifs. Peut-être que je suis mal compris / mal compris?

Modifier Je ne suis pas sûr que ma question porte à confusion. Forcé d’isoler la question:

Ma question avec précision: les nombres positifs sont-ils stockés en binary as is que les nombres négatifs sont stockés en two's complement à two's complement ?

Certains disent que tous sont stockés dans un complément à deux et une réponse indique que seuls les nombres négatifs sont stockés en complément à deux.

Commençons par résumer les types de données primitifs Java:

octet : le type de données d’octet est un entier de complément à deux signé de 8 bits.

Short : Le type de données abrégé est un entier de complément à deux signé de 16 bits.

int: Le type de données Int est un entier de complément à deux signé de 32 bits.

long: Le type de données long est un entier de complément à deux signés de 64 bits.

float: le type de données flottant est un virgule flottante IEEE 754 32 bits à simple précision.

double : le type de données double est un virgule flottante IEEE 754 64 bits à double précision.

booléen: le type de données booléen représente un bit d’information .

char: le type de données char est un caractère Unicode 16 bits unique .

La source

Complément à deux

“Le bon exemple est de wiki que la relation au complément de deux est réalisée en notant que 256 = 255 + 1, et (255 – x) est le complément de x

0000 0111 = le complément à 7 deux est 1111 1001 = -7

la façon dont cela fonctionne est le msb (le bit le plus significatif) reçoit une valeur négative, donc dans le cas ci-dessus

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

Les entiers positifs sont généralement stockés sous forme de nombres binarys simples (1 est 1, 10 est 2, 11 est 3, etc.).

Les entiers négatifs sont stockés comme complément à deux de leur valeur absolue. Le complément à deux d’un nombre positif est, en utilisant cette notation, un nombre négatif.

La source

Depuis que j’ai reçu quelques points pour cette réponse, j’ai décidé de l’append plus d’informations.

Une réponse plus détaillée:

Entre autres, il existe quatre approches principales pour représenter les nombres positifs et négatifs en binary, à savoir:

  1. Magnitude Signée
  2. Le complément
  3. Complément à deux
  4. Biais

1. Magnitude Signée

Utilise le bit le plus significatif pour représenter le signe, les bits restants sont utilisés pour représenter la valeur absolue. Où 0 représente un nombre positif et 1 représente un nombre négatif , exemple:

 1011 = -3 0011 = +3 

Cette représentation est plus simple. Cependant, vous ne pouvez pas append de nombres binarys de la même manière que vous ajoutez des nombres décimaux, ce qui complique la mise en œuvre au niveau du matériel. De plus, cette approche utilise deux motifs binarys pour représenter les 0, 100 … 0 et 0 …. 0.

2. Complément

Dans cette représentation, nous inversons tous les bits d’un nombre donné pour trouver sa complémentarité. Par exemple:

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

Le problème de cette représentation est qu’il existe encore deux modèles de bits pour représenter le 0 (00..0 et 11..1)

3. Deux compléments

Pour trouver le négatif d’un nombre, dans cette représentation, nous inversons tous les bits, puis ajoutons un bit. L’ajout d’un bit résout le problème d’avoir des modèles de deux bits représentant 0. Dans cette représentation, nous n’en avons qu’un (00 … 0).

Par exemple, nous voulons trouver la représentation binary négative de 4 (décimal) en utilisant 4 bits. D’abord, nous convertissons 4 en binary:

 4 = 0100 

alors nous inversons tous les bits

 0100 -> 1011 

enfin on ajoute un bit

 1011 + 1 = 1100. 

Donc, 1100 équivaut à -4 en décimal, si nous utilisons une représentation binary avec complément à deux avec 4 bits.

Un moyen plus rapide de trouver le complément consiste à fixer le premier bit à la valeur 1 et à inverser les bits restants. Dans l’exemple ci-dessus, ce serait quelque chose comme:

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

La représentation de deux compléments, en plus d’avoir une seule représentation pour 0, ajoute aussi deux valeurs binarys de la même manière qu’en décimal, avec des nombres pairs avec des signes différents. Néanmoins, il est nécessaire de vérifier les cas de débordement.

4. biais

Cette représentation est utilisée pour représenter l’exposant dans la norme IEEE 754 pour les points flottants. Il a l’avantage que la valeur binary avec tous les bits à zéro représente la plus petite valeur. Et la valeur binary avec tous les bits à 1 représente la plus grande valeur. Comme son nom l’indique, la valeur est codée (positive ou négative) en binary avec n bits avec un biais (normalement 2 ^ (n-1) ou 2 ^ (n-1) -1).

Donc, si nous utilisons 8 bits, la valeur 1 en décimal est représentée en binary en utilisant un biais de 2 ^ (n-1), par la valeur:

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

Les entiers Java sont de 32 bits et sont toujours signés. Cela signifie que le bit le plus significatif (MSB) fonctionne comme le bit de signe. L’entier représenté par un int n’est rien d’autre que la sum pondérée des bits. Les poids sont atsortingbués comme suit:

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

Notez que le poids du bit de poids fort est négatif (le plus grand négatif possible en fait), donc quand ce bit est activé, le nombre entier (la sum pondérée) devient négatif.

Simulons-le avec des nombres à 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 

Donc, la chose complémentaire de deux n’est pas un schéma exclusif pour représenter des entiers négatifs, on peut plutôt dire que la représentation binary des entiers est toujours la même, on ne fait que nier le poids du bit le plus significatif. Et ce bit détermine le signe de l’entier.

En C, il existe un mot-clé unsigned (non disponible en Java), qui peut être utilisé pour déclarer unsigned int x; . Dans les entiers non signés, le poids du MSB est positif ( 2^31 ) plutôt que négatif. Dans ce cas, l’intervalle d’un unsigned int est compris entre 0 et 2^32 - 1 , tandis qu’un int a une plage comprise entre -2^31 et 2^31 - 1 .

D’un autre sharepoint vue, si vous considérez le complément à deux de x comme ~x + 1 (PAS x plus un), voici l’explication:

Pour tout x , ~x est juste l’inverse binary de x , donc là où x a un 1 bit, ~x aura un 0 bit (et vice versa). Donc, si vous les ajoutez, il n’y aura pas de retenue dans l’addition et la sum sera juste un nombre entier égal à 1 .

Pour les entiers 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 

Le 1 bit le plus à gauche sera simplement supprimé, car il ne rentre pas dans 32 bits (débordement d’entier). Alors,

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

Vous pouvez donc voir que le négatif x peut être représenté par ~x + 1 , que nous appelons le complément à deux de x .

J’ai couru le programme suivant pour le savoir

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

La sortie est

 1010 11111111111111111111111111110110 

De la sortie, il semble qu’il utilise le complément à deux.

Oracle fournit une documentation concernant les types de données Java que vous pouvez trouver intéressants. Plus précisément:

int: Le type de données int est un entier de complément à deux signé de 32 bits. Il a une valeur minimale de -2 147 483 648 et une valeur maximale de 2 147 483 647 (inclus).

Btw, short est également stocké en complément à deux.

Selon ce document , tous les entiers sont signés et stockés au format de complément à deux pour Java. Pas sûr de sa fiabilité.

Le bit le plus significatif (32nd) indique que le nombre est positif ou négatif. Si c’est 0, cela signifie que le nombre est positif et qu’il est stocké dans sa représentation binary réelle. mais si c’est 1, cela signifie que le nombre est négatif et est stocké dans la représentation de son complément à deux. Donc, lorsque nous donnons un poids de -2 ^ 32 au 32ème bit tout en restaurant la valeur entière à partir de sa représentation binary, nous obtenons la réponse réelle.

Merci, dreamcrash pour la réponse https://stackoverflow.com/a/13422442/1065835 ; Sur la page wiki, ils donnent un exemple qui m’a aidé à comprendre comment trouver la représentation binary de la contrepartie négative d’un nombre positif.

Par exemple, en utilisant 1 octet (= 2 octets = 8 bits), le nombre décimal 5 est représenté par

0000 01012 Le bit le plus significatif est 0, le motif représente donc une valeur non négative. Pour convertir en −5 en notation à complément à deux, les bits sont inversés; 0 devient 1 et 1 devient 0:

1111 1010 À ce stade, le chiffre est le complément de la valeur décimale −5. Pour obtenir le complément à deux, 1 est ajouté au résultat, donnant:

1111 1011 Le résultat est un nombre binary signé représentant la valeur décimale −5 sous forme de complément à deux. Le bit le plus significatif est 1, donc la valeur représentée est négative.

Les nombres positifs sont stockés / retracés tels quels.

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

Mais les nombres négatifs seront stockés après le complément de 2 (autre que le bit MSB) et le bit MSB sera mis à 1.

par exemple) en stockant -10 puis

  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 

lors de la récupération, il a constaté que MSB est défini sur 1. Donc, il est négatif non. Et le complément à 2 sera effectué autre que MSB.

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

Fonderie

Notez également que lorsque vous lancez int / short en octet, seul le dernier octet sera considéré avec le dernier octet MSB,

Prenons l’exemple “-130” court, il pourrait être stocké comme ci-dessous

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

Maintenant, le transtypage des octets a pris le dernier octet qui est 0111 1110. (0-MSB) Puisque MSB dit qu’il est de valeur + ve, il sera donc pris tel quel. Ce qui est 126. (+ ve).

Prenez un autre exemple “130” court, il pourrait être stocké comme ci-dessous

  0-000 000 1000 0010 (MSB = 0) 

Maintenant, le transtypage des octets a pris le dernier octet, soit 1000 0010. (1 = MSB) Puisque MSB indique qu’il s’agit de la valeur -ve, le complément à 2 sera effectué et le nombre négatif sera renvoyé. Donc dans ce cas -126 sera retourné.

  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) (octet) -1 AND (int) (court) (octet) -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) 

De même

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

Mais

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

ET

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

Les références

Pourquoi le complément à deux est-il utilisé pour représenter des nombres négatifs?

Qu’est-ce que “Complément de 2”?

les nombres positifs sont stockés directement en tant que binarys. 2 compliment est requirejs pour les nombres négatifs.

par exemple:

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

voici la différence de bit signé.

Pour un entier positif, la valeur du complément 2 est la même que pour le bit MSB 0 (like +14 2'complement is 01110) .

Pour le nombre entier négatif seulement, nous calculons la valeur du complément 2 ‘ (-14= 10001+1 = 10010) .

Donc, la réponse finale est que les valeurs (+ve and -ve) sont stockées uniquement sous forme de complément à 2 ‘.