55 votes

Que représente 'x << ~y' en JavaScript ?

Que représente 'x << ~y' en JavaScript ?

J'ai cru comprendre que la méthode bit à bit SHIFT C'est ce que fait l'opération :

x << y AS x \* 2y

Et un tilde ~ L'opérateur le fait :

~x AS -(x+1)

Donc, je suppose ce qui suit :

5 << ~3 AS 5 \* 2\-4 or 5 \* Math.pow(2, -4)

Elle devrait aboutir à 0.3125 .

Mais, quand j'exécute 5 << ~3 il en résulte 1342177280 .

Qu'est-ce qu'une explication étape par étape ? Comment et pourquoi cette combinaison d'opérations aboutit-elle à 1342177280 au lieu de 0.3125 ?

(Cette question est similaire à la question de Stack Overflow <em><a href="http://stackoverflow.com/questions/276706/what-are-bitwise-operators">Que sont les opérateurs binaires ? </a></em>à propos de la méthode du bit <code>SHIFT</code> opérateur.)

53voto

Jaromanda X Points 12007

x << -n est égal à x << (32 - n)
~3 == -4 donc
5 << ~3 === 5 << (32 - 4) === 5 << 28 qui est 1,342,177,280

pour être précis X << -n n'est pas la même chose que X << (32 - n) ... en fait c'est à la fois plus simple et plus compliqué ... la plage valide d'un opérateur de décalage de bits est de 0 à 31 ... le RHS dans un opérateur de décalage de bits est d'abord converti en un entier non signé de 32 bits, puis masqué avec 31 (hex 1f) (binaire). 11111 )

                   3 = 00000000000000000000000000000011  
                  ~3 = 11111111111111111111111111111100
       0x1f (the mask) 00000000000000000000000000011111
                       --------------------------------
            ~3 & 0x1f  00000000000000000000000000011100 = 28

lorsque la magnitude est inférieure à 32, c'est exactement la même chose que ce que j'ai posté ci-dessus.

Les opérations sur les bits fonctionnent avec des entiers de 32 bits. Les décalages de bits négatifs n'ont aucun sens et sont donc transformés en nombres entiers positifs de 32 bits.

Comment le << opérateur travaux

Le rhs est converti en un entier 32bit non signé - comme expliqué ici ToUInt32

ToUint32 prend un nombre et retourne le nombre modulo 2^32.

22voto

Spencer Wieczorek Points 7722

Le site ~ retourne les bits de l'élément, tandis que l'opérateur << est un décalage à gauche par bit. Voici ce qui se passe en binaire, étape par étape. _Notez que le bit le plus à gauche étant 1 signifie un nombre négatif, ce format est le suivant compliment à deux_ :

3         // (00000000000000000000000000000011 => +3 in decimal)
// ~ flips the bits
~3        // (11111111111111111111111111111100 => -4 in decimal)
// The number 5 (..00101) shifted by left by -4 (-4 unsigned -> 28)
5         // (00000000000000000000000000000101 => +5 in decimal)
5 << -4   // (01010000000000000000000000000000 => +1342177280 in decimal)

Dans la dernière ligne, les bits sont décalés et "tournés" vers l'autre côté, ce qui donne un grand nombre positif. En fait, le décalage par un nombre négatif est similaire à une rotation par bit ( les bits débordés sont tournés vers l'autre côté. ), alors que les décalages par des nombres positifs n'ont pas ce comportement. L'inconvénient est que les bits non tournés ne sont pas pris en compte. Cela signifie essentiellement que 5 << -4 c'est la même chose que de faire 5 << (32 - 4) que la rotation est en fait un grand déplacement.

Le raisonnement est le suivant : les décalages de bits ne sont que de 5 bits. non signé entier. Donc le nombre binaire en complément à deux -4 (11100) non signé serait 28 .

9voto

hkBst Points 420

Votre analyse est correcte, sauf que vous ne devez pas interpréter ~3 (11100) (le complément binaire de 3 (00011)) comme -4 , mais comme un entier non signé (c'est-à-dire non négatif) de 5 bits, à savoir 28 = 16 + 8 + 4 (11100).

Ceci est expliqué dans le Norme ECMAScript ( NB dans la plupart des machines modernes, les nombres entiers positifs et négatifs sont représentés en mémoire à l'aide des éléments suivants complément à deux représentation) :

12.8.3 L'opérateur de décalage à gauche ( << )

REMARQUE Effectue une opération de décalage bit à bit vers la gauche sur l'opérande de gauche de la quantité spécifiée par l'opérande de droite.

12.8.3.1 Sémantique de l'exécution : Évaluation

ShiftExpression : ShiftExpression << AdditiveExpression

  1. Soit lref le résultat de l'évaluation de ShiftExpression.
  2. Que lval soit GetValue(lref).
  3. ReturnIfAbrupt(lval).
  4. Soit rref le résultat de l'évaluation de AdditiveExpression.
  5. Que rval soit GetValue(rref).
  6. ReturnIfAbrupt(rval).
  7. Que lnum soit ToInt32(lval).
  8. ReturnIfAbrupt(lnum).
  9. Laissez rnum être ToUint32(rval).
  10. ReturnIfAbrupt(rnum).
  11. Que shiftCount soit le résultat du masquage de tous les bits sauf les 5 bits les moins significatifs de rnum, c'est-à-dire calculer rnum & 0x1F.
  12. Renvoie le résultat du décalage à gauche de lnum par les bits de shiftCount. Le résultat de résultat est un nombre entier signé de 32 bits.

7voto

Mr_Pouet Points 344

~x inversera la représentation binaire de votre valeur x (valeur signée de 32 bits avec complément à deux).

x << y est l'opérateur de décalage à gauche (ici à gauche). Votre interprétation mathématique est correcte :)

Vous pouvez en savoir plus sur les opérations par bit ici : Opérateurs binaires en Javascript

6voto

Yeldar Kurmangaliyev Points 14018

5 << ~3 donne le même résultat que 5 << -4 vous avez raison.

Chose importante : le déplacement x << y se traduit réellement par x * 2 y mais ce n'est pas une utilisation directe, c'est juste un effet secondaire utile.
De plus, si vous avez une y cela ne fonctionne pas de la même manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X