web-dev-qa-db-fra.com

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

J'essaie de comprendre comment Java enregistre l'entier en interne). Je sais tout Java). Les entiers primitifs sont signés (sauf les courts?). Cela signifie un bit de moins disponible dans un octet pour le numéro.

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

Je vois que la spécification dit 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

Éditer

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 à deux alors:

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

Ici encore, la confusion est le signe dit, les deux sont des nombres négatifs. Peut-être que je me trompe/me trompe?

Edit Pas sûr que ma question déroute. Forcé d'isoler la question:

Ma question précise: 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 le complément à deux et qu'une réponse indique que seuls les nombres négatifs sont stockés en tant que complément à deux.

75
Kevin Rave

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

byte: Le type de données d'octet est un entier signé de 8 bits entier du complément à deux.

Short: Le type de données court est un signe signé de 16 bits complément du complément à deux.

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

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

float: Le type de données Float est une simple précision virgule flottante IEEE 754 32 bits.

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

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

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

Source

Complément à deux

"Le bon exemple vient 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 à 1 de x

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

la façon dont cela fonctionne est que le bit de poids fort (le bit le plus significatif) reçoit une valeur négative de sorte

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

Les entiers positifs sont généralement stockés sous forme de simples nombres binaires (1 vaut 1, 10 vaut 2, 11 vaut 3 et ainsi de suite).

Les entiers négatifs sont stockés en tant que complément à deux de leur valeur absolue. Le complément à deux d'un nombre positif correspond à l'utilisation d'un nombre négatif lorsque cette notation est utilisée.

Source

Depuis que j'ai reçu quelques points pour cette réponse, j'ai décidé d'y ajouter plus d'informations.

Une réponse plus détaillée:

Il existe quatre approches principales pour représenter les nombres positifs et négatifs en binaire, à savoir:

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

2. Un complément

Dans cette représentation, nous inversons tous les bits d'un nombre donné pour en découvrir le complément. Par exemple:

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

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

3. Un complément à deux

Pour trouver le négatif d'un nombre, dans cette représentation, nous inversons tous les bits, puis nous en ajoutons un. Ajouter un bit résout le problème d'avoir des motifs à 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 négative binaire de 4 (décimal) en utilisant 4 bits. Premièrement, nous convertissons 4 en binaire:

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 binaire à complément de Two avec 4 bits.

Un moyen plus rapide de trouver la complémentarité 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 Complément deux, en plus de n'avoir qu'une représentation pour 0, elle ajoute également deux valeurs binaires de la même manière qu'en décimal, des nombres pairs avec des signes différents. Néanmoins, il est nécessaire de vérifier les cas de débordement.

4. Bias

Cette représentation est utilisée pour représenter l'exposant dans la norme IEEE 754 pour les points flottants. L'avantage est 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 une polarisation (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
90
dreamcrash

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). Ainsi, lorsque ce bit est activé, le nombre entier (la somme 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

Ainsi, le complément à deux n'est pas un schéma exclusif pour la représentation des nombres entiers négatifs. Nous pouvons plutôt dire que la représentation binaire des nombres entiers est toujours la même, nous nions simplement 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 d'être négatif. Dans ce cas, la plage d'un unsigned int est 0 à 2^32 - 1, alors que int a la plage -2^31 à 2^31 - 1.

D'un autre point de 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 n'est que l'inverse au niveau des bits de x, donc partout où x a un 1- bit, ~x aura un 0- bit là-bas (et vice versa). Donc, si vous les additionnez, il n'y aura pas de retenue 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 plus à gauche 1bits seront simplement supprimés, car ils ne tiennent 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.

56
0605002

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

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

10
Dungeon Hunter

Oracle fournit une documentation sur Java types de données = que vous pourriez trouver intéressante. Plus précisément:

int: le type de données int est un entier complémentaire du 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 tant que complément à deux.

4
matsev

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

3
Joel

Le bit le plus significatif (32ème) indique que le nombre est positif ou négatif. S'il vaut 0, cela signifie que le nombre est positif et qu'il est stocké dans sa représentation binaire réelle. mais s'il vaut 1, cela signifie que le nombre est négatif et qu'il est stocké dans la représentation du complément à deux. Ainsi, lorsque nous accordons un poids de -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
Sazzadur Rahaman

Les nombres positifs sont stockés/reçus 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 à 2 (autre que le bit MSB) et le bit MSB sera mis à 1.

par exemple) lors du stockage de -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 exécuté 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.

Moulage

Notez également que lorsque vous convertissez int/short to byte, seul le dernier octet sera considéré avec le dernier octet MSB.

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

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

Maintenant, la conversion d'octets a pris le dernier octet qui est 0111 1110. (0-MSB) Etant donné que MSB dit que c'est la valeur + ve, elle sera prise telle quelle. Ce qui est 126. (+ ve).

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

  0-000 000 1000 0010     (MSB = 0)

Maintenant, la conversion d'octets a pris le dernier octet qui est 1000 0010. (1 = MSB) Etant donné que MSB dit que sa valeur est -ve, le complément à 2 sera exécuté et un 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) (car) (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. 

Les 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
Kanagavelu Sugumar

Merci, dreamcrash pour la réponse https://stackoverflow.com/a/13422442/1065835 ; sur la page du 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 bits = 8 bits), le nombre décimal 5 est représenté par

0000 01012 Le bit de poids fort est 0, le motif représente donc une valeur non négative. Pour convertir en −5 en notation du 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, ce qui donne:

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

2
Maksim Dmitriev

les nombres positifs sont stockés directement sous forme 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 en bit signé.

1
Siva Padhy

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

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

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

1
Mangesh Gawali