web-dev-qa-db-fra.com

Pourquoi préférer le complément de deux par rapport au signe et à l'ampleur pour les numéros signés?

Je suis juste curieux de savoir s'il y a une raison pour laquelle, pour représenter -1 en binaire, le complément à deux est utilisé: retourner les bits et ajouter 1?

-1 est représenté par 11111111 (complément à deux) plutôt que (à mon sens plus intuitif) 10000001, qui est un binaire 1 avec le premier bit comme drapeau négatif.

Avertissement: je ne compte pas sur l'arithmétique binaire pour mon travail!

190
Ray

C'est fait pour que l'addition n'ait pas besoin de logique particulière pour traiter les nombres négatifs. Découvrez l'article sur Wikipedia .

Disons que vous avez deux nombres, 2 et -1. Dans votre manière "intuitive" de représenter des nombres, ils seraient 0010 et 1001, respectivement (je m'en tiens à 4 bits pour la taille). À la manière du complément à deux, ils sont 0010 et 1111. Maintenant, disons que je veux les ajouter.

L'ajout de complément à deux est très simple. Vous ajoutez normalement des nombres et tout bit de retenue à la fin est rejeté. Donc, ils sont ajoutés comme suit:

  0010
+ 1111
=10001
= 0001 (discard the carry)

0001 est 1, résultat attendu de "2 + (- 1)".

Mais dans votre méthode "intuitive", l'ajout est plus compliqué:

  0010
+ 1001
= 1011

Quel est -3, non? Une simple addition ne fonctionne pas dans ce cas. Vous devez noter que l'un des nombres est négatif et utiliser un algorithme différent si c'est le cas.

Pour cette méthode de stockage "intuitive", la soustraction est une opération différente de l'addition, nécessitant des vérifications supplémentaires sur les nombres avant de pouvoir les ajouter. Puisque vous voulez que les opérations les plus élémentaires (addition, soustraction, etc.) soient aussi rapides que possible, vous devez stocker les nombres de manière à utiliser les algorithmes les plus simples possibles.

De plus, dans la méthode de stockage "intuitive", il y a deux zéros:

0000  "zero"
1000  "negative zero"

Qui sont intuitivement le même nombre mais qui ont deux valeurs différentes lorsqu’elles sont stockées. Chaque application devra prendre des mesures supplémentaires pour s'assurer que les valeurs non nulles ne sont pas non plus négatives à zéro.

Cette méthode offre un autre avantage, tel que de stocker les entiers, et vous devez étendre la largeur du registre dans lequel la valeur est stockée. Avec un complément à deux, enregistrer un nombre de 4 bits dans un registre de 8 bits consiste bit le plus significatif:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1110 (negative two, in four bits)
11111110 (negative two, in eight bits)

Il suffit de regarder le signe du mot plus petit et de le répéter jusqu'à ce qu'il occupe la largeur du mot le plus gros.

Avec votre méthode, vous devez effacer le bit existant, ce qui est une opération supplémentaire en plus du remplissage:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1010 (negative two, in four bits)
10000010 (negative two, in eight bits)

Vous devez toujours définir ces 4 bits supplémentaires dans les deux cas, mais dans le cas "intuitif", vous devez également effacer le cinquième bit. C'est une infime étape supplémentaire dans l'une des opérations les plus fondamentales et les plus courantes présentes dans chaque application.

317
Welbog

Wikipedia dit tout:

Le système à complément à deux présente l'avantage de ne pas nécessiter que les circuits d'addition et de soustraction examinent les signes des opérandes pour déterminer s'il convient d'ajouter ou de soustraire. Cette propriété rend le système à la fois plus simple à mettre en œuvre et capable de gérer facilement des calculs arithmétiques de précision supérieure. De plus, zéro n'a qu'une seule représentation, éliminant les subtilités associées au zéro négatif, qui existe dans les systèmes à complément à un.

En d'autres termes, l'ajout est identique, que le nombre soit négatif ou non.

18
Yacoby

Même si cette question est ancienne, laissez-moi mettre mes 2 centimes.

Avant d’expliquer cela, revenons à l’essentiel. Le complément 2 'est le complément à 1 + 1. Maintenant, quel est le complément de 1 et quelle est sa signification en plus.

La somme de tout nombre à n bits et de son complément à 1 vous donne le plus grand nombre possible pouvant être représenté par ces n-bits. Exemple:

 0010 (2 in 4 bit system)
+1101 (1's complement of 2)
___________________________
 1111  (the highest number that we can represent by 4 bits)

Maintenant, qu'arrivera-t-il si nous essayons d'ajouter 1 de plus au résultat. Il en résultera un débordement.

Le résultat sera 1 0000 qui est 0 (comme nous travaillons avec des nombres de 4 bits, (le 1 à gauche est un débordement)

Alors ,

Any n-bit number + its 1's complement = max n-bit number
Any n-bit number + its 1'complement + 1 = 0 ( as explained above, overflow will occur as we are adding 1 to max n-bit number)

Quelqu'un a alors décidé d'appeler le complément à 1 + 1 comme complément à 2 '. Ainsi, la déclaration ci-dessus devient: Tout nombre n'bit + son complément à 2 = 0, ce qui signifie complément à 2 d'un nombre = - (de ce nombre)

Tout ceci nous amène à une autre question: pourquoi ne peut-on utiliser que le (n-1) des n bits pour représenter un nombre positif et pourquoi le nième bit le plus à gauche représente-t-il le signe (0 sur le bit le plus à gauche signifie + ve, et 1 signifie -ve numéro). par exemple, pourquoi n'utilisons-nous que les 31 premiers bits d'un entier in Java pour représenter un nombre positif si le 32ème bit est égal à 1, c'est un nombre -ve.

 1100 (lets assume 12 in 4 bit system)
+0100(2's complement of 12)
___________________________

1 0000 (le résultat est zéro, avec le report 1 débordant)

Ainsi, le système de (n + 2 'complément de n) = 0 fonctionne toujours. La seule ambiguïté ici est que le complément à 2 de 12 est 0100, ce qui représente également + 8 de façon ambiguë, sauf que -12 représente le système de complément à 2.

Ce problème sera résolu si les nombres positifs ont toujours un 0 dans leur bit le plus à gauche. Dans ce cas, leur complément à 2 aura toujours un 1 dans leur bit le plus à gauche, et nous n'aurons pas l'ambiguïté du même ensemble de bits représentant un nombre de complément à 2 ainsi qu'un nombre + ve.

12
Rpant

Complément à deux permet aux additions et aux soustractions d'être effectuées de la manière habituelle (comme pour les nombres non signés). Cela empêche également -0 (une manière distincte de représenter 0 qui ne serait pas égal à 0 avec la méthode normale de comparaison des nombres, bit par bit).

8
Zifre

c'est pour simplifier les sommes et les différences de nombres. une somme d'un nombre négatif et d'un nombre positif codé par 2 est la même chose que de les résumer normalement.

6
Stefano Verna

L’implémentation habituelle de l’opération est "retourner les bits et ajouter 1", mais il existe une autre façon de le définir qui rend probablement la justification plus claire. Le complément à 2 est la forme que vous obtenez si vous prenez la représentation non signée habituelle dans laquelle chaque bit contrôle la puissance suivante de 2 et ne fait que rendre négatif le terme le plus significatif.

Prenant une valeur de 8 bits asept une6 une5 une4 une3 une2 une1 une

L'interprétation binaire non signée habituelle est:
2sept*unesept + 26*une6 + 25*une5 + 24*une4 + 23*une3 + 22*une2 + 21*une1 + 2*une
11111111 = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255

L'interprétation du complément à deux est:
- 2sept*unesept + 26*une6 + 25*une5 + 24*une4 + 23*une3 + 22*une2 + 21*une1 + 2*une
11111111 = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1

Aucun des autres bits ne change du tout le sens, et porte dans unsept est "débordé" et ne devrait pas fonctionner, donc pratiquement toutes les opérations arithmétiques fonctionnent sans modification (comme d’autres l’ont noté). La magnitude de signe inspecte généralement le bit de signe et utilise une logique différente.

5
puetzk

Pour développer d'autres réponses:

En complément de deux

  • L'ajout est le même mécanisme que l'ajout d'entiers positifs simples.
  • La soustraction ne change pas aussi
  • La multiplication aussi!

La division nécessite un mécanisme différent.

Tous ces éléments sont vrais, car le complément à deux n'est que de l'arithmétique modulaire normale, où nous choisissons de considérer certains nombres comme négatifs en soustrayant le modulo.

4
yairchu

Le complément à deux permet d’additionner des nombres négatifs et positifs sans logique particulière.

Si vous avez essayé d'ajouter 1 et -1 en utilisant votre méthode
10000001 (-1)
+ 00000001 (1)
vous obtenez
10000010 (-2)

Au lieu de cela, en utilisant le complément à deux, nous pouvons ajouter

11111111 (-1)
+ 00000001 (1) vous obtenez
00000000 (0)

La même chose est vraie pour la soustraction.

En outre, si vous essayez de soustraire 4 de 6 (deux nombres positifs), vous pouvez compléter le complément de 2 et ajouter les deux ensemble 6 + (-4) = 6 - 4 = 2

Cela signifie que la soustraction et l'addition des nombres positifs et négatifs peuvent toutes être effectuées par le même circuit dans l'unité centrale.

4
CodeFusionMobile

En lisant les réponses à cette question, je suis tombé sur ce commentaire [édité].

Le complément de 2 de 0100 (4) sera 1100. Maintenant, 1100 est 12 si je dis normalement. Donc, quand je dis 1100 normal, il est 12, mais quand je dis complément à 2, il est -4? En outre, dans Java quand 1100 (supposons 4 bits pour le moment) est stocké, puis comment est-il déterminé s'il s'agit de +12 ou -4 ?? - hagrawal le 2 juillet à 16:53

À mon avis, la question posée dans ce commentaire est très intéressante et j'aimerais donc tout d'abord la reformuler, puis donner une réponse et un exemple.

QUESTION - Comment le système peut-il déterminer comment un ou plusieurs octets adjacents doivent être interprétés? En particulier, comment le système peut-il déterminer si une séquence d'octets donnée est un nombre binaire simple ou un nombre complémentaire de 2?

REPONSE - Le système établit comment interpréter une séquence d'octets via des types. Les types définissent

  • combien d'octets doivent être considérés
  • comment ces octets doivent être interprétés

EXEMPLE - Nous supposons ci-dessous que

  • Les char ont une longueur de 1 octet
  • short 'a une longueur de 2 octets
  • int 'et float' ont 4 octets de long

Veuillez noter que ces tailles sont spécifiques à mon système. Bien qu’ils soient assez communs, ils peuvent être différents d’un système à l’autre. Si vous êtes curieux de savoir ce qu'ils sont sur votre système, utilisez le opérateur sizeof .

Tout d’abord, nous définissons un tableau contenant 4 octets et nous les initialisons tous au nombre binaire 10111101, correspondant au nombre hexadécimal BD.

// BD(hexadecimal) = 10111101 (binary)
unsigned char   l_Just4Bytes[ 4 ]   =   { 0xBD, 0xBD, 0xBD, 0xBD };

Ensuite, nous lisons le contenu du tableau en utilisant différents types.

unsigned char et signed char

// 10111101 as a PLAIN BINARY number equals 189
printf( "l_Just4Bytes as unsigned char  -> %hi\n", *( ( unsigned char* )l_Just4Bytes ) );

// 10111101 as a 2'S COMPLEMENT number equals -67
printf( "l_Just4Bytes as signed char    -> %i\n", *( ( signed char* )l_Just4Bytes ) );

unsigned short et short

// 1011110110111101 as a PLAIN BINARY number equals 48573
printf( "l_Just4Bytes as unsigned short -> %hu\n", *( ( unsigned short* )l_Just4Bytes ) );

// 1011110110111101 as a 2'S COMPLEMENT number equals -16963
printf( "l_Just4Bytes as short          -> %hi\n", *( ( short* )l_Just4Bytes ) );

unsigned int, int et float

// 10111101101111011011110110111101 as a PLAIN BINARY number equals 3183328701
printf( "l_Just4Bytes as unsigned int   -> %u\n", *( ( unsigned int* )l_Just4Bytes ) );

// 10111101101111011011110110111101 as a 2'S COMPLEMENT number equals -1111638595
printf( "l_Just4Bytes as int            -> %i\n", *( ( int* )l_Just4Bytes ) );

// 10111101101111011011110110111101 as a IEEE 754 SINGLE-PRECISION number equals -0.092647
printf( "l_Just4Bytes as float          -> %f\n", *( ( float* )l_Just4Bytes ) );

Les 4 octets dans RAM (l_Just4Bytes[ 0..3 ]) restent toujours exactement les mêmes. La seule chose qui change, c'est la façon dont nous les interprétons.

De nouveau, nous disons au système comment les interpréter à travers types .

Par exemple, ci-dessus, nous avons utilisé les types suivants pour interpréter le contenu du l_Just4Bytes tableau

  • unsigned char: 1 octet en binaire simple
  • signed char: 1 octet dans le complément à 2
  • unsigned short: 2 octets en notation binaire simple
  • short: 2 octets dans le complément à 2
  • unsigned int: 4 octets en notation binaire simple
  • int: 4 octets en complément de 2
  • float: 4 octets en notation simple précision IEEE 754

[EDIT] Cet article a été édité après le commentaire de user4581301. Merci d'avoir pris le temps de laisser tomber ces quelques lignes utiles!

2
mw215

Vous pouvez voir le professeur Jerry Cain de Stanford expliquer le complément des deux, lors de la deuxième conférence (l'explication concernant le complément des deux commence vers 13 heures) de la série de conférences intitulée Programming Paradigms disponible sur la chaîne YouTube de Standford. Voici le lien vers la série de conférences: http://www.youtube.com/view_play_list?p=9D558D49CA734A02 .

1
alexs

Un avantage majeur de la représentation en complément à deux qui n’a pas encore été mentionné ici est que les bits inférieurs d’une somme, d’une différence ou d’un produit en complément à deux dépendent uniquement sur les bits correspondants des opérandes. La raison pour laquelle la valeur signée sur 8 bits pour -1 est 11111111 est cet entier soustrayant tout nombre entier dont les 8 bits les plus bas sont 00000001 de tout autre entier dont les 8 bits les plus bas sont 0000000 donnera un entier dont les 8 bits les plus bas sont 11111111. Mathématiquement, la valeur -1 serait une chaîne infinie de 1, mais toutes les valeurs comprises dans la plage d'un type entier particulier seront toutes les 1 ou toutes les 0 après un certain point. Il est donc pratique pour les ordinateurs de "prolonger le signe" bit le plus significatif d'un nombre comme s'il représentait un nombre infini de 1 ou de 0.

Le complément à deux est à peu près la seule représentation de nombres signés qui fonctionne bien pour les types supérieurs à la taille naturelle du mot d'une machine binaire, car lors de l'addition ou de la soustraction, le code peut extraire le plus petit bloc de chaque opérande, calculer le plus petit bloc de le résultat et stockez-le, puis chargez le bloc suivant de chaque opérande, calculez le bloc suivant du résultat, et stockez-le, etc. Ainsi, même un processeur nécessitant que tous les ajouts et soustractions passe par un seul registre de 8 bits peut gérer des nombres signés 32 bits avec une efficacité raisonnable (plus lent qu'avec un registre 32 bits, bien sûr, mais toujours utilisable).

Lors de l'utilisation de toute autre représentation signée autorisée par le standard C, chaque bit du résultat peut potentiellement être affecté par un bit des opérandes, ce qui oblige soit à conserver une valeur entière dans les registres à la fois, soit à suivre les calculs avec un extra étape qui, dans au moins certains cas, nécessite la lecture, la modification et la réécriture de chaque bloc du résultat.

0
supercat

Nous effectuons uniquement des opérations d'addition pour les additions et les soustractions. Nous ajoutons le deuxième opérande au premier opérande pour l'addition. Pour la soustraction, nous ajoutons le complément à 2 du deuxième opérande au premier opérande.

Avec une représentation de complément à 2, nous n'avons pas besoin de composants numériques séparés pour la soustraction - seuls des additionneurs et des compléments sont utilisés.

0
subhakar

Eh bien, votre intention n'est pas vraiment d'inverser tous les bits de votre nombre binaire. Il s'agit en fait de soustraire chacun de son chiffre de 1. C'est une bonne coïncidence que soustraire 1 à 1 donne 0 et soustraire 0 à 1 donne 1. L'inversion de bits effectue donc cette soustraction.

Mais pourquoi trouvez-vous la différence entre chaque chiffre et 1? Eh bien, vous n'êtes pas. Votre intention réelle est de calculer la différence entre un nombre binaire donné et un autre nombre binaire comportant le même nombre de chiffres mais ne contenant que des 1. Par exemple, si votre numéro est 10110001, lorsque vous inversez tous ces bits, vous êtes effectivement en train de calculer (11111111 - 10110001).

Ceci explique la première étape dans le calcul du complément à deux. Maintenant, incluons la deuxième étape - en ajoutant 1 - également dans l'image.

Ajoutez 1 à l'équation binaire ci-dessus:

11111111 - 10110001 + 1

Qu'est ce que tu obtiens? Cette:

100000000 - 10110001

C'est l'équation finale. Et en effectuant ces deux étapes, vous essayez de trouver la dernière différence: le nombre binaire soustrait à un autre nombre binaire avec un chiffre supplémentaire et contenant des zéros, sauf à la position du bit le plus significatif.

Mais pourquoi voulons-nous vraiment cette différence? Eh bien, à partir de maintenant, je suppose que ce serait mieux si vous lisiez le article de Wikipedia .

0
Frederick The Fool

Il est intéressant de noter que sur certaines machines à additionner antérieures, avant l’époque des ordinateurs numériques, la soustraction était effectuée en demandant à l’opérateur de saisir les valeurs à l’aide d’un jeu de légendes de couleurs différentes sur chaque touche (ainsi chaque touche entrerait neuf moins le nombre à soustraite), et appuyer sur un bouton spécial supposerait un report dans un calcul. Ainsi, sur une machine à six chiffres, pour soustraire 1234 à une valeur, l'opérateur appuierait sur une touche indiquant normalement "998,765", puis sur un bouton pour ajouter cette valeur plus un au calcul en cours. L'arithmétique du complément à deux est simplement l'équivalent binaire de l'arithmétique antérieure du "complément à dix".

0
supercat

L'avantage d'effectuer la soustraction par la méthode du complément est la réduction du matériel
complexité.Il n'est pas nécessaire d'utiliser un circuit numérique différent pour l'addition et la soustraction.La double addition et la soustraction sont effectuées uniquement par additionneur.

0
user2640494

Le complément à deux est utilisé car il est plus simple à implémenter dans les circuits et ne permet pas non plus un zéro négatif.

S'il y a x bits, le complément à deux va de + (2 ^ x/2 + 1) à - (2 ^ x/2). Son complément va de + (2 ^ x/2) à - (2 ^ x/2), mais permet un zéro négatif (0000 est égal à 1000 dans un système de complément à 4 bits 1).

0
samoz