Entiers signés

Le problème

Sur un octet, on peut représenter les entiers compris entre 0 et \( 2^0+2^1+2^2+2^3+2^4+2^5+2^6+2^7 = 2^8-1 \) en les représentant en écriture binaire.
Mais si l'on veut également, sur ces huit bits, coder des entiers négatifs, comment procéder ?

Le complément à deux

Pour répondre à cette demande, on utilise en général la représentation explicitée ci-dessous (dite du complément à deux ).

Sur un octet, les 7 bits de poids faibles sont utilisés pour une représentation en base 2. Le bit de poids fort est utilisé pour le signe : ce bit sera à 0 pour un positif, et à 1 pour un négatif.

La convention utilisée est la suivante :

  • Un entier représenté sur un octet par 0b6b5b4b3b2b1b0 représente l'entier \( 0\times 2^7 +b_6 \times 2^6 +b_5 \times 2^5 + b_4 \times 2^4+b_3 \times 2^3+b_2 \times 2^2+b_1 \times 2^1+b_0 \times 2^0 \)
  • Tandis qu'un entier représenté sur un octet par 1b6b5b4b3b2b1b0 représente l'entier \( -1 \times 2^7 +b_6 \times 2^6 +b_5 \times 2^5 + b_4 \times 2^4+b_3 \times 2^3+b_2 \times 2^2+b_1 \times 2^1+b_0 \times 2^0 \)

On code ainsi les entiers entre 0 et 127 = 27-1 par :

CodedécimalSomme
0000 00000\(\small 0\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+0 \times 2^1+0 \times 2^0 \)
0000 00011\(\small 0\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+0 \times 2^1+1 \times 2^0 \)
0000 00102\(\small 0\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+1 \times 2^1+0 \times 2^0 \)
0000 00113\(\small 0\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+1 \times 2^1+1 \times 2^0 \)
.........
0111 1111\( 2^7-1 = 127 \) \(\small 0\times 2^7 +1 \times 2^6 +1 \times 2^5 + 1 \times 2^4+1 \times 2^3+1 \times 2^2+1 \times 2^1+1 \times 2^0 \)

et les entiers entre -128 et -1 par :

CodedécimalSomme
1000 0000-128\( \small -1\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+0 \times 2^1+0 \times 2^0 \)
1000 0001-127\(\small -1\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+0 \times 2^1+1 \times 2^0 \)
1000 0010-126\(\small -1\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+1 \times 2^1+0 \times 2^0 \)
1000 0011-125\(\small -1\times 2^7 +0 \times 2^6 +0 \times 2^5 + 0 \times 2^4+0 \times 2^3+0 \times 2^2+1 \times 2^1+1 \times 2^0 \)
.........
1111 1111\( -2^7+(2^7-1) = -1 \) \(\small -1\times 2^7 +1 \times 2^6 +1 \times 2^5 + 1 \times 2^4+1 \times 2^3+1 \times 2^2+1 \times 2^1+1 \times 2^0 \)

Le complément à deux sur deux octets

Si nous codons maintenant des entiers en complément à deux sur deux octets, la plage représentée n'est bien sûr plus la même.

0 est représenté par 0000 0000 0000 0000.

Les entiers positifs de 1 à \( 2^{15}-1 = 32767 \) sont codés par :

Codedécimal
0000 0000 0000 00011
0000 0000 0000 00102
......
0111 1111 1111 111132767

Les entiers négatifs de \( -2^{15} = -32768 \) à \( -1 \) sont codés par :

Codedécimal
1000 0000 0000 0000\( -32768 \)
1000 0000 0000 0010\( -32767 \)
......
1111 1111 1111 1111-1

Le complément à deux sur n bits

Les entiers naturels codés sont les entiers codés en binaire sur n-1 bits.
Ce sont les entiers entre 0 et \( \sum_{j=0}^{n-2} 2^j = 2^{n-1}-1 \).

Les entiers négatifs codés sont les mêmes entiers que précédemment, auxquels on soustrait l'entier 2n-1.
Ce sont les entiers entre \( -2^{n-1} \) et \( -2^{n-1} + \sum_{j=0}^{n-2} 2^j = -1 \).

Au total, il y a bien entendu 2n entiers représentés.

Décodage

Ainsi un code tel que 1000 0001 peut représenter 129 (représentation binaire sur 8 bits) ou -127 (complément à deux sur 8 bits).

Le logiciel qui utilisera un tel code devra donc évidemment "savoir" quelle est la convention utilisée.
Dans plusieurs langages de programmation, il existe deux types différents permettant une telle interprétation. En langage C par exemple, on utilise le type int (entiers signés) et le type unsigned int (entiers non signés).

Vous aurez remarquer également que l'expression "représentation en complément à 2" n'a pas de sens : il faut également préciser sur combien de bits pour connaître le bit interprétant le signe.
C'est ainsi qu'en langage C par exemple, on trouve des entiers de type int mais aussi des entiers de type short int : le nombre de bits utilisés n'est pas le même.