Qu'est-ce que le"complément 2"?
je suis en systèmes informatiques, et avoir été "151910920 du" mal , en partie, avec Complément à Deux . Je veux comprendre, mais tout ce que j'ai lu ne m'a pas apporté le portrait. J'ai lu l'article de wikipedia et divers autres articles, dont mon livre de texte .
donc, je voulais commencer ce wiki communautaire post à définissez ce Qu'est le complément de Two, comment l'utiliser et comment il peut affecter les nombres lors d'opérations comme les casts (de signé à non signé et vice versa), les opérations bit-wise et les opérations bit-shift.
ce que j'espère c'est une définition claire et concise qui est facilement comprise par un programmeur.
17 réponses
le complément de Two est une façon intelligente de stocker des entiers de sorte que les problèmes mathématiques communs sont très simples à mettre en œuvre.
pour comprendre, vous devez penser aux nombres en binaire.
ça dit en gros,
- pour zéro, utilisez tous les 0.
- pour les entiers positifs, commencez à compter, avec un maximum de 2 (nombre de bits - 1) -1.
- pour les entiers négatifs, faites exactement la même chose, mais changez le rôle des 0 et des 1 (donc au lieu de commencer avec 0000, commencez avec 1111 - c'est la partie "complément").
essayons avec un mini-byte de 4 bits (nous l'appellerons un nibble - 1/2 un byte).
-
0000
- zéro -
0001
un -
0010
- deux -
0011
- trois -
0100
à0111
- quatre à sept
C'est tout ce qu'on peut faire de positif. 2 3 -1 = 7.
pour négatifs:
-
1111
- négatif -
1110
- négatif deux -
1101
- négatif trois -
1100
à1000
- négatif quatre à négatif huit
notez que vous obtenez une valeur supplémentaire pour les négatifs ( 1000
= -8) que vous n'obtenez pas pour les positifs. C'est parce que 0000
est utilisé pour zéro. Cela peut être considéré comme ligne de numéro des ordinateurs.
distinction entre les nombres positifs et négatifs
ce Faisant, le premier bit obtient le rôle du bit "signe", car il peut être utilisé pour distinguer entre les valeurs décimales positives et négatives. Si le bit le plus significatif est 1
, alors le binaire peut être dit négatif, où comme si le bit le plus significatif (le plus à gauche) est 0
, vous pouvez dire discerne la valeur décimale est positif.
je me demande si cela pourrait être expliqué mieux que l'article de Wikipedia.
le problème de base que vous essayez de résoudre avec la représentation du complément de two est le problème de stocker des entiers négatifs.
considérons D'abord un entier non signé stocké en 4 bits. Vous pouvez avoir le
0000 = 0
0001 = 1
0010 = 2
...
1111 = 15
Ces sont pas signés, car il n'y a aucune indication qu'ils soient négatifs ou positifs.
Magnitude du signe et Notation excessive
pour stocker des nombres négatifs, vous pouvez essayer un certain nombre de choses. Tout d'abord, vous pouvez utiliser la notation de magnitude de signe qui assigne le premier bit comme un bit de signe pour représenter +/- et les bits restants pour représenter la magnitude. Donc en utilisant encore 4 bits et en supposant que 1 signifie - et 0 signifie + alors vous avez
0000 = +0
0001 = +1
0010 = +2
...
1000 = -0
1001 = -1
1111 = -7
alors, vous voyez le problème? Nous avons un 0 positif et négatif. Le plus gros problème est ajout et soustraction de nombres binaires. Les circuits à ajouter et à soustraire à l'aide de la magnitude du signe seront très complexes.
Ce qui est
0010
1001 +
----
?
un autre système est excès de notation . Vous pouvez stocker des nombres négatifs, vous vous débarrassez du problème des deux zéros mais l'addition et la soustraction restent difficiles.
ainsi vient le complément de two. Maintenant, vous pouvez stocker positif et entiers négatifs et effectuer l'arithmétique avec une facilité relative. Il existe un certain nombre de méthodes pour convertir un nombre en complément de deux. En voici une.
Convertir un nombre Décimal en Complément à Deux
-
convertissez le nombre en binaire (ignorez le signe pour le moment) par exemple 5 is 0101 et -5 is 0101
-
Si le nombre est un nombre positif, alors vous êtes fait. par exemple 5 is 0101 en binaire en utilisant deux notation du complément.
-
Si le nombre est négatif alors
3.1 trouver le complément (inverser les 0 et les 1) par exemple -5 est 0101 donc trouver le complément est 1010
3.2 ajouter 1 au complément 1010 + 1 = 1011. Par conséquent, -5 dans le complément de two est 1011.
Alors, que si vous vouliez faire 2 + (-3) en binaire? 2 + (-3) est -1. Que devriez-vous faire si vous utilisiez le signe magnitude pour ajouter ces nombres? 0010 + 1101 = ?
en utilisant le complément de two, pensez à quel point ce serait facile.
2 = 0010
-3 = 1101 +
-------------
-1 = 1111
conversion du complément de Two en décimal
conversion 1111 en décimal:
-
le nombre commence par 1, donc il est négatif, donc nous trouvons le complément de 1111, qui est 0000.
-
ajouter 1 à 0000, et on obtient 0001.
-
Convertissez 0001 en décimal, qui est 1.
-
appliquer le signe = -1.
Tada!
comme la plupart des explications que j'ai vues, celles ci-dessus sont claires sur la façon de travailler avec le complément de 2, mais n'expliquent pas vraiment ce qu'ils sont mathématiquement. Je vais essayer de le faire, pour les entiers au moins, et je vais couvrir un certain fond qui est probablement familier d'abord.
rappeler comment il fonctionne pour décimale:
2345
est une façon d'écrire
2 × 10 3 + 3 × 10 2 + 4 × 10 1 + 5 × 10 0 .
de la même manière, binaire est une façon d'écrire des nombres en utilisant juste 0 et 1 suivant la même idée générale, mais en remplaçant ces 10s ci-dessus par 2s. Puis en binaire,
1111
est une façon d'écrire
1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0
et si vous en sortir, qui s'avère égal à 15 (base 10). C'est parce que c'est
8+4+2+1 = 15.
tout cela est bien et bon pour les nombres positifs. Cela fonctionne même pour les nombres négatifs si vous êtes prêt à juste coller un signe moins en face d'eux, comme les humains le font avec des nombres décimaux. Cela peut même se faire dans les ordinateurs, en quelque sorte, mais je n'ai pas vu un tel ordinateur depuis le début des années 1970. Je vous laisse les raisons d'une autre discussion.
Pour les ordinateurs, il s'avère être plus efficace d'utiliser un complément la représentation des nombres négatifs. Et voici quelque chose qui est souvent négligé. Compléter les notations impliquent une sorte d'inversion des chiffres du nombre, même implicite des zéros qui précèdent une normale nombre positif. C'est maladroit, parce que la question se pose: tous? Cela pourrait être un nombre infini de chiffres à considérer.
heureusement, les ordinateurs ne représentent pas des infinités. Les nombres sont limités à une longueur particulière (ou largeur, si vous préférez). Revenons donc aux nombres binaires positifs, mais avec une taille particulière. J'utiliserai 8 chiffres ("bits") pour ces exemples. Donc, notre nombre binaire serait vraiment
00001111
ou
0 × 2 7 + 0 × 2 6 + 0 × 2 5 + 0 × 2 4 + 1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0
pour former le négatif du complément 2, Nous complétons d'abord tous les chiffres (binaires) pour former
11110000
et ajouter 1 au formulaire
11110001
mais comment comprendre que cela signifie -15?
la réponse est que nous changeons le sens du bit d'ordre supérieur (le plus à gauche). Ce bit sera un 1 pour tous les nombres négatifs. Le changement sera de changer le signe de sa contribution à la valeur du nombre, il apparaît dans. Donc maintenant notre 11110001 est compris pour représenter
- 1 × 2 7 + 1 × 2 6 + 1 × 2 5 + 1 × 2 4 + 0 × 2 3 + 0 × 2 2 + 0 × 2 1 + 1 × 2 0
tu as remarqué le " - " devant cette expression? Cela signifie que le bit de signe porte le poids -2 7 , c'est-à-dire -128 (base 10). Tous les autres postes conservent le même poids qu'ils avaient dans les numéros binaires non signés.
travailler notre -15, il est
-128 + 64 + 32 + 16 + 1
essayez votre calculatrice. c'est -15.
des trois principales façons dont j'ai vu les nombres négatifs représentés dans les ordinateurs, le complément de 2 gagne haut la main pour la commodité dans l'utilisation générale. Il a une curiosité, si. Puisque c'est binaire, il doit y avoir un nombre pair de combinaisons de bits possibles. Chaque nombre positif peut être jumelé avec son négatif, mais il n'y a qu'un zéro. Nier un zéro vous fait zéro. Il y a donc une autre combinaison, le numéro avec 1 dans le bit de signe et 0 partout ailleurs. Le nombre positif correspondant ne correspondrait pas au nombre de bits utilisés.
ce qui est encore plus étrange à propos de ce nombre est que si vous essayez de former son positif en complétant et en ajoutant un, vous obtenez le même nombre négatif en arrière. Il semble naturel que zero fasse cela, mais c'est inattendu et pas du tout le comportement auquel nous sommes habitués parce que les ordinateurs mis à part, nous pensons généralement à un approvisionnement illimité de chiffres, pas cette arithmétique à longueur fixe.
C'est comme la pointe d'un iceberg de bizarreries. Il y en a d'autres qui attendent sous la surface, mais ça suffit pour cette discussion. Vous pourriez probablement trouver plus si vous recherchez "débordement" pour l'arithmétique à point fixe. Si vous voulez vraiment entrer dans elle, vous pourriez également rechercher "arithmétique modulaire".
le complément de 2 est très utile pour trouver la valeur d'un binaire, mais j'ai pensé à une façon beaucoup plus concise de résoudre un tel problème (jamais vu quelqu'un d'autre le publier):
prendre un binaire, par exemple: 1101 [en supposant que l'espace "1" est le signe égale à -3 .
en utilisant le complément de 2, nous le ferions...flip 1101 à 0010...ajouter 0001 + 0010 = = = > nous donne 0011. 0011 en binaire Positif = 3. donc 1101 = -3 !
ce que j'ai réalisé:
au lieu de tout le retournement et l'ajout, vous pouvez juste faire la méthode de base pour résoudre pour un binaire positif (disons 0101) est (2 3 * 0) + (2 2 * 1) + (2 1 * 0) + (2 0 * 1) = 5.
Faire exactement le même concept avec un négatif!(avec un petit twist)
prendre 1101, par exemple:
pour le premier numéro au lieu de 2 3 * 1 = 8 , do -(2 3 * 1) = -8 .
, puis continuer comme d'habitude, en faisant -8 + (2 2 * 1) + (2 1 * 0) + (2 0 * 1) = -3
Imaginez que vous avez un nombre fini de bits/trits/chiffres/n'importe quoi. Vous définissez 0 comme tous les chiffres étant 0, et Compter vers le haut naturellement:
00
01
02
..
vous finirez par déborder.
98
99
00
nous avons deux chiffres et pouvons représenter tous les numéros de 0 à 100. Tous ces chiffres sont positifs! Supposons que nous voulions aussi représenter des nombres négatifs?
ce que nous avons vraiment c'est un cycle. Le numéro avant 2 est 1. Le le nombre avant 1 est 0. Le nombre Avant 0 est... 99 .
donc, pour simplifier, disons que tout nombre supérieur à 50 est négatif. "0", "49" représentent de 0 à 49. "99" est -1, " 98 " est -2, ... "50", c'est -50.
Cette représentation est dix complément . Les ordinateurs utilisent généralement complément de deux , qui est le même, sauf en utilisant des bits au lieu de chiffres.
la bonne chose au sujet du complément de ten est que l'ajout juste fonctionne . Vous n'avez pas besoin de faire quoi que ce soit de spécial pour ajouter des nombres positifs et négatifs!
deux complément est trouvé en ajoutant un à 1'st complément du nombre donné.
Disons que nous devons trouver deux complément de 10101
puis trouver son complément un, c'est-à-dire, 01010
ajouter 1
à ce résultat, c'est-à-dire, 01010+1=01011
, qui est la réponse finale.
permet d'obtenir la réponse 10-12 sous forme binaire en utilisant 8 bits: Ce que nous allons vraiment faire est de 10 + (-12)
nous devons obtenir la partie de compliment de 12 pour la soustraire de 10. 12 en binaire est 00001100. 10 en binaire est 00001010.
pour obtenir le compliment de la partie 12, on inverse tous les bits et on ajoute 1. 12 en binaire inversé est 11110011. C'est aussi le code Inverse (le complément). Maintenant, nous devons en ajouter un, qui est maintenant 11110100.
donc 11110100 est le compliment de 12! Facile quand on pense que de cette façon.
maintenant vous pouvez résoudre la question ci - dessus de 10-12 sous forme binaire.
00001010
11110100
-----------------
11111110
en regardant le système de complément des deux d'un point de vue mathématique, cela a vraiment du sens. En dix complément, l'idée est essentiellement "d'isoler" la différence.
exemple: 63-24 = x
nous ajoutons le complément de 24 qui est vraiment juste (100 - 24). Donc vraiment, tout ce que nous faisons est d'ajouter 100 sur les deux côtés de l'équation.
Maintenant, l'équation est: 100 + 63 - 24 = x + 100, c'est pourquoi nous enlever les 100 (ou 10 ou 1000 ou peu importe).
en raison de la situation peu pratique d'avoir à soustraire un nombre d'une longue chaîne de zéros, nous utilisons un 'complément Radix diminué' système, dans le système décimal, le complément de neuf.
lorsque nous sommes présentés avec un nombre soustrait d'une grande chaîne de neuf, nous avons juste besoin d'inverser les nombres.
exemple: 99999-03275 = 96724
C'est la raison, après neuf complément, nous ajoutons 1. Comme vous le savez probablement des maths de l'enfance, 9 devient 10 en 'volant' 1. Donc en gros, c'est juste le complément de ten qui prend 1 de la différence.
en binaire, le complément de two est égal au complément de ten, tandis que le complément de one est égal au complément de nine. La principale différence est qu'au lieu d'essayer d'isoler la différence avec les puissances de dix (ajouter 10, 100, etc. dans l'équation), nous essayons d'isoler la différence avec les puissances de deux.
C'est pour cette raison que nous inverser les bits. Tout comme notre minuend est une chaîne de nines en décimal, notre minuend est une chaîne de Nines en binaire.
exemple: 111111-101001 = 010110
parce que les chaînes de uns sont 1 en dessous d'un pouvoir agréable de deux, ils "volent" 1 de la différence comme neuf font dans décimal.
quand nous utilisons des nombres binaires négatifs, nous disons vraiment:
0000 - 0101 = x
1111 - 0101 = 1010
1111 + 0000 - 0101 = x + 1111
pour "isoler" x, nous devons ajouter 1 car 1111 est à une distance de 10000 et nous supprimons le 1 de tête car nous venons de l'ajouter à la différence originale.
1111 + 1 + 0000 - 0101 = x + 1111 + 1
10000 + 0000 - 0101 = x + 10000
il suffit de retirer 10000 des deux côtés pour obtenir x, c'est de base de l'algèbre.
plusieurs des réponses jusqu'à présent expliquent bien pourquoi le complément de two est utilisé pour représenter un nombre négatif, mais ne nous dites pas ce qu'est le complément de two, en particulier pas pourquoi un " 1 " est ajouté, et en fait souvent ajouté de manière erronée.
La confusion vient d'une mauvaise compréhension de la définition d'un complément de nombre. Un complément est la partie manquante qui ferait quelque chose de complet.
le complément radix d'un nombre à n chiffres x en radix b est, par définition, b^n-X. En binaire 4 est représenté par 100, qui a 3 chiffres (n=3) et un radix de 2 (b=2). Ainsi son complément radix est b^n-x = 2^3-4=8-4=4 (ou 100 en binaire).
Cependant, en binaire obtenir un complément radix n'est pas aussi facile que d'obtenir son complément radix diminué, qui est défini comme (b^n-1)-y, juste 1 de moins que celui du complément radix. Pour obtenir un complément radix diminué, vous retournez simplement tous les chiffres.
100 - > 011 (diminution du complément radix)
pour obtenir le complément radix (deux), nous ajoutons simplement 1, comme la définition définie.
011 +1 ->100 (complément de two).
maintenant, avec cette nouvelle compréhension, regardons l'exemple donné par Vincent Ramdhanie (voir ci-dessus la deuxième réponse)
/ * début de Vincent
conversion 1111 en décimal:
Le nombre commence par 1, donc c'est négatif, donc on trouve le complément de 1111, qui est 0000. Ajoutez 1 à 0000, et on obtient 0001. Convertissez 0001 en décimal, qui est 1. Appliquer le signe = -1. Tada!
fin de Vincent * /
doit être compris comme
le nombre commence par 1, donc c'est négatif. Donc nous savons que c'est un complément à deux d'une certaine valeur X. Pour trouver le x représenté par le complément de ses deux, nous devons d'abord trouver ses 1 compléter.
le complément de deux de x: 1111 complément de x: 1111-1 ->1110; x = 0001, (retourner tous les chiffres)
appliquer le signe -, et la réponse =-x =-1.
c'est un moyen astucieux d'encoder des entiers négatifs de telle manière qu'environ la moitié de la combinaison de bits d'un type de données sont réservés pour des entiers négatifs, et l'addition de la plupart des entiers négatifs avec leurs entiers positifs correspondants résulte en un report débordement qui laisse le résultat à un zéro binaire.
ainsi, dans le complément de 2 si on est 0x0001 puis -1 est 0x1111, parce que cela résultera en une somme combinée de 0x0000 (avec un débordement de 1).
2: lorsque nous en ajoutons un avec les compléments 1 d'un nombre, nous obtenons les compléments 2. Par exemple: 100101 c'est 1 effectif 011010 et complément de 2 est 011010+1 = 011011 (Par l'ajout de l'un avec le 1er complément) Pour plus d'informations cet article expliquer graphiquement.
j'ai aimé la réponse de lavinio, mais le changement de bits ajoute une certaine complexité. Il y a souvent le choix de déplacer des bits tout en respectant le bit de signe ou en ne respectant pas le bit de signe. C'est le choix entre traiter les nombres comme signés (-8 à 7 pour un nibble, -128 à 127 pour les octets) ou les nombres non signés de gamme complète (0 à 15 pour les nibbles, 0 à 255 pour les octets).
j'ai eu le même problème il y a quelques semaines. J'ai fini par lire sur le sujet en ligne à partir de diverses sources, en essayant de rassembler les morceaux, et en écrivant à ce sujet moi-même juste pour s'assurer que je l'ai compris correctement. Nous utilisons le complément de two pour deux raisons principales:
- pour éviter les représentations multiples de 0
- pour éviter de garder la trace de l'embout de transport (comme dans son complément) en cas de débordement.
- La réalisation d'opérations simples comme l'addition et la soustraction devient facile.
si vous voulez une explication plus détaillée de la question, essayez l'article écrit par moi ici . Espérons que cela aide!
j'ai lu une explication fantastique sur Reddit par jng, en utilisant l'odomètre comme une analogie.
il s'agit d'une convention utile. Les mêmes circuits et opérations logiques que ajouter / soustraire des nombres positifs en binaire encore travailler à la fois positif et les nombres négatifs si vous utilisez la convention, c'est pourquoi il est si utile et omniprésente.
Imaginez le compteur kilométrique d'une voiture, il roule à (dire) 99999. Si vous incrément 00000 vous obtenez 00001. Si vous décrétez 00000, vous obtenez 99999 (en raison de la mise en autour de vous). Si vous ajoutez un retour à 99999 il remonte à 00000. Il est donc utile de décider que 99999 représente -1. De même, il est très utile de décider que 99998 représente -2, et ainsi de suite. Vous avez arrêter quelque part, et aussi, par convention, la moitié supérieure de l'numéros sont réputés être négatifs (50000-99999), et moitié inférieure positive il suffit de se tenir debout (00000-49999). En conséquence, le chiffre supérieur être 5-9 signifie que le nombre représenté est négatif, et il est 0-4 les moyens de l'est positif exactement le même que le haut bits représentation d'un signe dans un nombre binaire de complément à deux.
comprendre que c'était difficile pour moi aussi. Une fois je l'ai eu et je suis retourné à re-lire les livres, articles et explications (il n'y avait pas internet de retour à l'époque), il s'est avéré beaucoup de ceux qui décrivent il n'a pas vraiment la comprendre. J'ai écrit un livre enseignant le langage de l'Assemblée après cela (qui s'est bien vendu pendant 10 ans).
référence: https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
j'inverse tous les bits et j'ajoute 1. Programmatically:
// in C++11
int _powers[] = {
1,
2,
4,
8,
16,
32,
64,
128
};
int value=3;
int n_bits=4;
int twos_complement = (value ^ ( _powers[n_bits]-1)) + 1;
vous pouvez également utiliser une calculatrice en ligne pour calculer la représentation binaire de deux compléments d'un nombre décimal: http://www.convertforfree.com/twos-complement-calculator/
la réponse la plus simple:
1111 + 1 = (1)0000. Donc 1111 doit être -1. Puis -1 + 1 = 0.
c'est parfait pour comprendre tout ça pour moi.