Comment les entiers sont-ils représentés en interne à un niveau de bits en Java?

J'essaie de comprendre comment Java stocke integer en interne. Je sais que tous les entiers primitifs java sont signés, (sauf court?). Que signifie un peu moins disponible dans un octet pour le nombre.

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

Je vois que les spécifications disent 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 all les nombres sont stockés comme complément de deux alors:

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

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

Modifier Je ne suis pas sûr que ma question soit déroutante. Forcé d'isoler la question:

Ma question précisément: les nombres positifs sont-ils stockés dans binary as is tandis que les nombres négatifs sont stockés comme two's complement?

Certains ont dit que tous sont stockés dans deux complément et une réponse dit que seuls les nombres négatifs sont stockés en tant que complément de deux.

68
demandé sur ArtB 2012-11-16 22:22:40

10 réponses

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

Byte : le type de données Byte est un entier de complément signé à 8 bits.

Short : le type de données Short est un entier de complément à deux signé sur 16 bits.

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

Long: le type de données Long est un entier de complément à deux signé 64 bits.

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

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

Booléen: boolean type de données représente un bit d'information.

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

Source

Le complément de deux

"Le bon exemple est de wiki que la relation avec le 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 = 7 le complément de deux est 1111 1001= -7

La façon dont cela fonctionne est que le msb (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 binaires simples (1 est 1, 10 est 2, 11 est 3 et ainsi de suite).

Négatif les entiers sont stockés en tant que complément des deux de leur valeur absolue. Le complément à deux d'un nombre positif est, lors de l'utilisation de cette notation, un nombre négatif.

Source

Depuis que j'ai reçu quelques points pour cette réponse, j'ai décidé de l'ajouter 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 binaire, à savoir:

  1. signé L'ampleur
  2. son complément
  3. complément de deux
  4. biais

1. Signé Ampleur

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 ajouter de nombres binaires de la même manière que vous ajoutez des nombres décimaux, ce qui rend plus difficile à mettre en œuvre au niveau du matériel. De plus, cette approche utilise deux modèles binaires pour représenter le 0, 100...0 et 0....0.

2. Un 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. Le complément de deux

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

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

4 = 0100

Ensuite, nous inversons tous les bits

0100 -> 1011

Enfin, nous ajoutons un peu

1011 + 1 = 1100.

Donc 1100 est équivalent à -4 en décimal, si nous utilisons une représentation binaire de complément à deux avec 4 bits.

Un moyen plus rapide de trouver le complémentaire est de fixer le premier bit comme valeur 1 et d'inverser les bits restants. Dans l'exemple ci-dessus, ce serait quelque chose comme:

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

Représentation du complément de deux, en plus d'avoir une seule représentation pour 0, Il ajoute également deux valeurs binaires de la même manière qu'en décimal, nombres pairs avec différents signer. 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 binaire avec tous les bits à zéro représente la plus petite valeur. Et la valeur binaire 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 binaire 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 binaire 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
77
répondu dreamcrash 2017-05-23 12:18:14

Les entiers Java sont de 32 bits, et 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 somme pondérée des bits. Les poids sont attribué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 MSB est négatif (le plus grand négatif possible en fait), donc quand ce bit est activé, le nombre entier (la somme pondérée) devient négatif.

Simulons-le avec 4 bits nombre:

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, le complément des deux n'est pas un schéma exclusif pour représenter des entiers négatifs, nous pouvons plutôt dire que la représentation binaire des entiers est toujours la même, nous nions simplement le poids du bit le plus significatif. Et que peu détermine le signe de l'entier.

En C, il y a 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 étant négatif. Dans ce cas, la portée d'un unsigned int est 0 à 2^32 - 1, tandis que int a range -2^31 à 2^31 - 1.

D'un autre point de vue, si vous considérez le complément des deux de x comme ~x + 1 (PAS x plus UN), Voici l'explication:

, Pour tout x, ~x est juste le bit à bit inverse de x, donc où x est un 1 bits, ~x aura un 0-bits (et vice versa). Donc, si vous les additionnez, il n'y aura pas de report dans l'addition et la somme sera juste un entier dont chaque bit est 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 ignoré, car il ne correspond pas à 32 bits (dépassement d'entier). Donc,

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

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

52
répondu 0605002 2014-10-05 07:36:31

J'ai couru le programme suivant pour le savoir

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 sortie est

1010
11111111111111111111111111110110

De la sortie, il semble qu'il a utilisé le complément de deux.

8
répondu Dungeon Hunter 2013-06-30 17:24:04

Oracle fournit une documentation concernant Java Datatypes que vous pouvez trouver intéressante. Plus précisément:

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

Btw, short est également stocké en tant que complément de deux.

3
répondu matsev 2012-11-16 18:35:49

Selon ce document , tous les entiers sont signés et stockés dans le format de complément de deux pour java. Pas certain de sa fiabilité..

3
répondu Joel 2014-08-04 19:20:35

Le bit Le plus significatif (32e) 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 binaire réelle. mais si c'est 1, cela signifie que le nombre est négatif et est stocké dans la représentation du complément de ses deux. Donc, quand nous donnons du poids -2^32 au 32e bit tout en restaurant la valeur entière à partir de sa représentation binaire, nous obtenons la réponse réelle.

2
répondu Sazzadur Rahaman 2012-11-16 18:57:45

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

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

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

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

1111 1011 le résultat est un nombre binaire signé représentant 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.

2
répondu Maksim Dmitriev 2017-05-23 12:03:06

Les nombres positifs sont stockés / récupérés tels quels.

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. 

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

Par exemple) lors du stockage de -10 alors

  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. Il est donc négatif non. Et le complément de 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 retrived.

Casting

Notez également que lorsque vous lancez int/court d'octets, seul le dernier octet sera considéré avec le dernier octet MSB,

Prenez l'exemple "-130" court, il peut être stocké comme ci-dessous

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

Maintenant, la coulée d'octets a pris le dernier octet qui est 0111 1110. (0-MSB) Puisque MSB dit qu'il s'agit d'une valeur +ve, il sera donc pris tel quel. Qui est de 126. (+ve).

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

  0-000 000 1000 0010     (MSB = 0)

Maintenant, la coulée d'octets a pris le dernier octet qui est 1000 0010 . (1 = MSB) Puisque MSB dit que c'est - valeur ve, le complément de 2 sera effectué et le nombre négatif sera retourné. 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 et(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. 

Références

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

Qu'est-ce que le "complément 2"?

2
répondu Kanagavelu Sugumar 2017-05-23 10:31:17

Les nombres positifs sont stockés directement en tant que binaire. Le compliment de 2 est requis pour les nombres négatifs.

Par exemple:

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

Voici la différence dans le bit signé.

1
répondu Siva Padhy 2014-02-07 06:59:52

Pour l'entier positif 2 ' la valeur de complement est la même avec le bit MSB 0 (like +14 2'complement is 01110).

Pour seulement un entier négatif seulement, nous calculons la valeur de 2'complément (-14= 10001+1 = 10010).

Donc la réponse finale est à la fois les valeurs(+ve and -ve) sont stockées sous forme de 2'complément seulement.

1
répondu Mangesh Gawali 2016-12-27 17:50:00