Comment fonctionne l'opérateur de complément au niveau du bit (~ tilde)?


Réponses:


283

N'oubliez pas que les nombres négatifs sont stockés comme complément à deux de la contrepartie positive. A titre d'exemple, voici la représentation de -2 en complément à deux: (8 bits)

1111 1110

La façon dont vous obtenez cela est de prendre la représentation binaire d'un nombre, de prendre son complément (inverser tous les bits) et d'en ajouter un. Deux commence comme 0000 0010, et en inversant les bits, nous obtenons 1111 1101. En ajouter un nous donne le résultat ci-dessus. Le premier bit est le bit de signe, ce qui implique un négatif.

Voyons donc comment nous obtenons ~ 2 = -3:

En voici encore deux:

0000 0010

Retournez simplement tous les bits et nous obtenons:

1111 1101

Eh bien, à quoi ressemble -3 dans le complément à deux? Commencez par le positif 3: 0000 0011, retournez tous les bits à 1111 1100 et ajoutez-en un pour devenir une valeur négative (-3), 1111 1101.

Donc, si vous inversez simplement les bits en 2, vous obtenez la représentation complémentaire à deux de -3.

L'opérateur de complément (~) JUST FLIPS BITS. C'est à la machine d'interpréter ces bits.


44
Une autre chose à mentionner est peut-être que le flip est appelé complément 1s, avant d'ajouter le 1.
Chris S

3
Cela pourrait aider d'autres personnes qui ne sont pas conscientes du complément à un et du complément à deux. Lisez à leur sujet ici. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai

1
N'est-ce pas l'opérateur NOT au niveau du bit?
Braden Best

3
Comment la machine sait-elle qu'elle obtient un nombre négatif à deux complémentaires au lieu d'un nombre positif plus élevé? Est-ce à cause du système de type de la langue respective indiquant que le type est un entier signé par rapport à non signé?
GL2014

@ GL2014 Je pense que vous avez répondu à votre propre question. Selon moi, c'est ainsi que la machine a été conçue pour fonctionner en premier lieu.
geekidharsh

40

~ retourne les bits dans la valeur.

Pourquoi ~2est -3a à voir avec la façon dont les nombres sont représentés au niveau du bit. Les nombres sont représentés comme un complément à deux .

Donc, 2 est la valeur binaire

00000010

Et ~ 2 retourne les bits pour que la valeur soit maintenant:

11111101

Qui, est la représentation binaire de -3.


2
N'est-ce pas 11111101 == décimal 253 vs -3?
AKS

10
Dépend s'il représente un entier signé ou non signé.
driis

Quelle est son utilisation dans la programmation du monde réel? A-t-il des applications dans la programmation concurrentielle?
Noah J. Standerson il y a

18

Comme d'autres l'ont mentionné, il ~suffit de retourner les bits (change un à zéro et zéro à un) et puisque le complément à deux est utilisé, vous obtenez le résultat que vous avez vu.

Une chose à ajouter est la raison pour laquelle le complément à deux est utilisé, c'est pour que les opérations sur les nombres négatifs soient les mêmes que sur les nombres positifs. Pensez -3au nombre auquel 3il faut ajouter pour obtenir zéro et vous verrez que ce nombre est 1101, rappelez-vous que l'addition binaire est comme l'addition (décimale) de l'école élémentaire seulement vous en portez un lorsque vous arrivez à deux au lieu de 10 .

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

Par conséquent 1101est -3, retourner les morceaux que vous obtenez ce 0010qui est deux.


8

Cette opération est un complément, pas une négation.

Considérez que ~ 0 = -1, et travaillez à partir de là.

L'algorithme de négation est "complément, incrément".

Le saviez-vous? Il y a aussi "un complément à un" où les nombres inverses sont symétriques, et il a à la fois un 0 et un -0.


6

Je sais que la réponse à cette question est postée il y a longtemps, mais je voulais partager ma réponse pour la même chose.

Pour trouver le complément à un d'un nombre, trouvez d'abord son équivalent binaire. Ici, le nombre décimal 2est représenté sous 0000 0010forme binaire. Prenons maintenant son complément à un en inversant (en retournant tous les 1 en 0 et tous les 0 en 1) tous les chiffres de sa représentation binaire, ce qui entraînera:

0000 0010 → 1111 1101

C'est le complément à un du nombre décimal 2. Et puisque le premier bit, c'est-à-dire que le bit de signe est 1 dans le nombre binaire, cela signifie que le signe est négatif pour le nombre qu'il a stocké. (ici, le nombre auquel il est fait référence n'est pas 2 mais le complément à un de 2).

Maintenant, puisque les nombres sont stockés en tant que complément à 2 (en prenant le complément à un d'un nombre plus un), donc pour afficher ce nombre binaire 1111 1101,, en décimal, nous devons d'abord trouver son complément à 2, qui sera:

1111 1101 → 0000 0010 + 1 → 0000 0011

C'est le complément des 2. La représentation décimale du nombre binaire,, 0000 0011est 3. Et, puisque le bit de signe était un comme mentionné ci-dessus, la réponse qui en résulte est -3.

Astuce: Si vous lisez attentivement cette procédure, vous auriez observé que le résultat de l'opérateur complément à un est en fait le nombre (opérande - sur lequel cet opérateur est appliqué) plus un avec un signe négatif. Vous pouvez également essayer cela avec d'autres numéros.


Pourquoi ajoute-t-il deux fois? Je vois add, flip, add. 0010-> 0011-> 1100->1101
Braden Best

1
C'est flip, flip, ajouter. Premier retournement pour le complément à 1. Et puisque, il est stocké dans le complément à 2 dans le système, lorsque vous devez afficher le nombre, il affichera le complément à 2 du nombre stocké (c'est-à-dire, le deuxième retournement et l'ajout).
Himanshu Aggarwal

Mais flip (flip (2)) ne serait-il pas juste 2? 0010 1101 0010
Braden Best

Oui, ce ne sera que 2. Mais puisque lorsque les bits sont stockés en mémoire, le bit le plus significatif était 1, ce qui rendra le nombre négatif plus tard comme expliqué dans la réponse ci-dessus.
Himanshu Aggarwal

1
D'après ce que vous décrivez et tout ce que j'ai recherché, ce n'est pas un complément à deux, mais un complément «régulier», ou PAS au niveau du bit. En logique, NOT 0 = 1et NOT 1 = 0. Dans un système à quatre bits, NOT 0011(3) = 1100(12 non signés, -4 signés). D'après ce que je comprends, le complément à deux est défini comme (NOT n) + 1, et est utilisé pour trouver la contrepartie négative d'un nombre quel que soit le nombre de bits. Ainsi, 2c(5) = -5. Voyez, maintenant c'est parfaitement logique. Tant que vous appelez cette opération ce qu'elle est: PAS au niveau du bit.
Braden Best

4

int a = 4; System.out.println (~ a); Le résultat serait: -5

'~' de tout entier en java représente le complément de 1 du no. par exemple je prends ~ 4, ce qui signifie en représentation binaire 0100. d'abord, la longueur d'un entier est de quatre octets, soit 4 * 8 (8 bits pour 1 octet) = 32. Ainsi, dans la mémoire système, 4 est représenté par 0000 0000 0000 0000 0000 0000 0000 0100 maintenant ~ l'opérateur effectuera le complément de 1 sur le non binaire ci-dessus

c'est-à-dire 1111 1111 1111 1111 1111 1111 1111 1011-> 1 complément le bit le plus significatif représente le signe du non (soit - ou +) si c'est 1 alors le signe est '-' si c'est 0 alors le signe est '+' comme par ce notre résultat est un nombre négatif, en java les nombres négatifs sont stockés sous la forme du complément de 2, le résultat acquis que nous devons convertir en complément de 2 (effectuez d'abord le complément de 1 et ajoutez simplement 1 au complément de 1). tous les un deviendront des zéros, sauf le bit le plus significatif 1 (qui est notre représentation par signe du nombre, c'est-à-dire pour les 31 bits restants 1111 1111 1111 1111 1111 1111 1111 1011 (résultat acquis de ~ opérateur) 1000 0000 0000 0000 0000 0000 0000 0000 0100 (complément à 1)

1 (complément à 2)

1000 0000 0000 0000 0000 0000 0000 0101 maintenant le résultat est -5 consultez ce lien pour la vidéo <[Opérateurs par bits en java] https://youtu.be/w4pJ4cGWe9Y


2

Simplement ...........

En tant que complément à 2 de n'importe quel nombre, nous pouvons calculer en inversant tous les 1 en 0 et vice-versa que nous y ajoutons 1.

Ici, N = ~ N produit des résultats - (N + 1) toujours. Parce que le système stocke les données sous forme de complément à 2, ce qui signifie qu'il stocke ~ N comme ceci.

  ~N = -(~(~N)+1) =-(N+1). 

Par exemple::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

Maintenant, le point est d'où vient Minus. Mon avis est supposé que nous ayons un registre de 32 bits, ce qui signifie 2 ^ 31 -1 bits impliqués dans le fonctionnement et un bit de repos qui change dans le calcul précédent (complément) stocké sous forme de bit de signe qui est généralement 1. Et nous obtenons le résultat comme ~ 10 = -11.

~ (-11) = 10;

Ce qui précède est vrai si printf ("% d", ~ 0); nous obtenons le résultat: -1;

Mais printf ("% u", ~ 0) que le résultat: 4294967295 sur une machine 32 bits.


1

L'opérateur de complément au niveau du bit (~) est un opérateur unaire .

Cela fonctionne selon les méthodes suivantes

Tout d'abord, il convertit le nombre décimal donné en sa valeur binaire correspondante. Dans le cas de 2, il convertit d'abord 2 en 0000 0010 (en nombre binaire de 8 bits).

Ensuite, il convertit tous les 1 du nombre en 0 et tous les zéros en 1; puis le nombre deviendra 1111 1101.

c'est la représentation du complément à 2 de -3.

Pour trouver la valeur non signée en utilisant le complément, c'est-à-dire simplement pour convertir 1111 1101 en décimal (= 4294967293), nous pouvons simplement utiliser le% u lors de l'impression.


1

Je pense que pour la plupart des gens, la confusion vient de la différence entre le nombre décimal et le nombre binaire signé, alors clarifions-le d'abord:

pour le monde décimal humain: 01 signifie 1, -01 signifie -1, pour le monde binaire de l'ordinateur: 101 signifie 5 s'il n'est pas signé. 101 signifie (-4 + 1) si est signé alors que le chiffre signé est à la position x. | X

donc le bit retourné en 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 la confusion vient du mélange du résultat signé (101 = -3) et du résultat non scintillant (101 = 5)


1

tl; dr ~ retourne les bits. En conséquence, le signe change. ~2est un nombre négatif ( 0b..101). Pour émettre un nombre négatif de rubycopies -, puis le complément de deux ~2: -(~~2 + 1) == -(2 + 1) == 3. Les nombres positifs sont sortis tels quels.

Il existe une valeur interne et sa représentation sous forme de chaîne. Pour les entiers positifs, ils coïncident essentiellement:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

Ce dernier étant équivalent à:

irb(main):003:0> 2.to_s
"2"

~retourne les bits de la valeur interne. 2est 0b010. ~2est 0b..101. Deux points ( ..) représentent un nombre infini de 1's. Puisque le bit le plus significatif (MSB) du résultat est 1, le résultat est un nombre négatif ( (~2).negative? == true). Pour sortir un nombre négatif rubys'imprime -, puis le complément à deux de la valeur interne. Le complément à deux est calculé en retournant les bits, puis en ajoutant 1. Le complément de deux 0b..101est 3. En tant que tel:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

Pour résumer, il retourne les bits, ce qui change le signe. Pour sortir un nombre négatif, il imprime -, puis ~~2 + 1( ~~2 == 2).

La raison pour laquelle rubygénère des nombres négatifs comme ça, c'est parce qu'il traite la valeur stockée comme un complément à deux de la valeur absolue. En d'autres termes, ce qui est stocké l'est 0b..101. C'est un nombre négatif, et en tant que tel, c'est un complément à deux d'une certaine valeur x. Pour trouver x, il fait un complément à deux 0b..101. Qui est le complément à deux du complément à deux de x. Ce qui est x(par exemple ~(~2 + 1) + 1 == 2).

Dans le cas où vous appliquez ~à un nombre négatif, il retourne simplement les bits (ce qui change néanmoins le signe):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

Ce qui est plus déroutant, c'est que ~0xffffff00 != 0xff(ou toute autre valeur avec MSB égale à 1). Simplifions un peu: ~0xf0 != 0x0f. C'est parce qu'il traite 0xf0comme un nombre positif. Ce qui a du sens. Ainsi, ~0xf0 == 0x..f0f. Le résultat est un nombre négatif. Le complément de deux 0x..f0fest 0xf1. Alors:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

Dans le cas où vous n'allez pas appliquer d'opérateurs binaires au résultat, vous pouvez considérer ~comme un -x - 1opérateur:

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

Mais ce n'est sans doute pas très utile.

Un exemple Supposons que vous receviez un masque de réseau 8 bits (pour simplifier) ​​et que vous vouliez calculer le nombre de 0. Vous pouvez les calculer en retournant les bits et en appelant bit_length( 0x0f.bit_length == 4). Mais ~0xf0 == 0x..f0f, nous devons donc couper les éléments inutiles:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

Ou vous pouvez utiliser l'opérateur XOR ( ^):

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"

0

Nous devons d'abord diviser le chiffre donné en ses chiffres binaires puis l'inverser en ajoutant au dernier chiffre binaire.Après cette exécution, nous devons donner le signe opposé au chiffre précédent celui dont nous trouvons le complément ~ 2 = -3 Explication : La forme binaire 2s est 00000010 changements en 11111101 c'est un complément à uns, puis complétés 00000010 + 1 = 00000011 qui est la forme binaire de trois et avec -sign Ie, -3


0

L'opérateur binaire est un opérateur unaire qui fonctionne sur la méthode du signe et de la magnitude selon mon expérience et mes connaissances.

Par exemple, ~ 2 donnerait -3.

Cela est dû au fait que l'opérateur binaire représenterait d'abord le nombre en signe et en amplitude qui est 0000 0010 (opérateur 8 bits) où MSB est le bit de signe.

Ensuite, plus tard, il prendrait le nombre négatif de 2 qui est -2.

-2 est représenté par 1000 0010 (opérateur 8 bits) en signe et en magnitude.

Plus tard, il ajoute un 1 au LSB (1000 0010 + 1) qui vous donne 1000 0011.

Ce qui est -3.


0

Javascript tilde (~) contraint une valeur donnée au complément à un - tous les bits sont inversés. C'est tout ce que fait Tilde. Ce n'est pas un signe d'opinion. Il n'ajoute ni ne soustrait aucune quantité.

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

Sur les processeurs de bureau standard utilisant des langages de haut niveau comme JavaScript, l'arithmétique signée BASE10 est la plus courante, mais gardez à l'esprit qu'elle n'est pas la seule. Les bits au niveau du processeur sont sujets à interprétation en fonction d'un certain nombre de facteurs. Au niveau du «code», dans ce cas JavaScript, ils sont interprétés comme un entier signé 32 bits par définition (laissons les flottants en dehors de cela). Pensez-y comme quantique, ces 32 bits représentent de nombreuses valeurs possibles à la fois. Cela dépend entièrement de l'objectif de conversion dans lequel vous les visualisez.

JavaScript Tilde operation (1's complement)

BASE2 lens
~0001 -> 1110  - end result of ~ bitwise operation

BASE10 Signed lens (typical JS implementation)
~1  -> -2 

BASE10 Unsigned lens 
~1  -> 14 

Tout ce qui précède est vrai en même temps.


0

Fondamentalement, l'action est un complément et non une négation.

Ici, x = ~ x produit des résultats - (x + 1) toujours.

x = ~ 2

- (2 + 1)

-3

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.