Différence entre >>> et >>

Réponses:

408

>>est un décalage arithmétique à droite, >>>est un décalage logique à droite.

Dans un décalage arithmétique, le bit de signe est étendu pour conserver la signature du nombre.

Par exemple: -2 représenté sur 8 bits serait 11111110(car le bit le plus significatif a un poids négatif). Le déplacer d'un bit vers la droite en utilisant le décalage arithmétique vous donnerait 11111111, ou -1. Le décalage à droite logique, cependant, ne se soucie pas que la valeur puisse éventuellement représenter un nombre signé; il déplace tout simplement vers la droite et remplit à partir de la gauche avec des 0. Décaler notre bit de droite de -2 en utilisant le décalage logique donnerait 01111111.

danben
la source
8
Bien que je sois d'accord et que j'apprécie que les décalages arithmétiques puissent être utilisés pour multiplier les nombres signés par 2^k, je trouve bizarre que ce soit la réponse de tout le monde. Une chaîne de bits n'est pas un nombre et >>peut toujours être utilisée sur n'importe quelle chaîne de bits: elle fait toujours la même chose quel que soit le rôle que joue cette chaîne de bits et qu'elle ait ou non un concept de `` signe ''. Serait-il correct d'étendre votre réponse déjà excellente avec une discussion sur le cas où votre opérande n'est pas interprété comme un numéro signé? Ma plainte est-elle logique?
Ziggy
11
Pourquoi dites-vous qu'une chaîne de bits n'est pas un nombre? Diriez-vous qu'une séquence de chiffres décimaux n'est pas un nombre?
danben
4
@danben Discuter s'il s'agit ou non d'un nombre n'a de sens que si vous le liez à un contexte. Si Internet n'est que de l'électricité, je conviens qu'une chaîne n'est qu'un nombre.
bvdb
1
@danben mais en fait, je pense à quoi Ziggy faisait vraiment référence (à mon humble avis), c'est qu'un Stringpourrait aussi être considéré comme un char[]. Il ne dit pas que a charn'est pas un nombre; il dit juste que c'est un numéro non signé . Je pense que c'est là qu'il a perdu.
bvdb
5
@Ziggy a raison: toutes les chaînes de bits ne sont pas un nombre et toutes les séquences de chiffres décimaux ne sont pas un nombre. Par exemple: les numéros de téléphone, les codes postaux (dans de nombreux pays), etc. sont des chaînes de chiffres décimaux, mais cela n'a pas de sens de les ajouter, de les soustraire ou de les multiplier, donc ce ne sont pas vraiment des nombres. Il s'agit de chaînes de chiffres décimaux, mais elles doivent être traitées comme des chaînes de caractères. (Les codes postaux au Canada et au Royaume-Uni contiennent des lettres et des chiffres.)
jcsahnwaldt indique GoFundMonica
102

>>>est shift non signé; il insérera 0. >>est signé et étendra le bit de signe.

Opérateurs de quart JLS 15.19

Les opérateurs de décalage incluent le décalage gauche <<, le décalage droit signé >>et le décalage droit non signé >>>.

La valeur de n>>sest des positions de bits ndécalées vers la droite savec extension de signe .

La valeur de n>>>sest des positions de bits ndécalées vers la droite savec une extension nulle .

    System.out.println(Integer.toBinaryString(-1));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >> 16));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >>> 16));
    // prints "1111111111111111"

Pour rendre les choses plus claires en ajoutant une contrepartie positive

System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"

Puisqu'il est positif, les décalages signés et non signés ajouteront 0 au bit le plus à gauche.

Questions connexes

polygénelubrifiants
la source
Sans vos exemples, je ne comprendrais pas.
mr5
47

Ils sont à la fois décalage vers la droite, mais >>>estunsigned

De la documentation :

L'opérateur de décalage à droite non signé ">>>" décale un zéro dans la position la plus à gauche, tandis que la position la plus à gauche après ">>" dépend de l'extension du signe.

Mat
la source
12
pouvez-vous expliquer avec un exemple
Kasun Siyambalapitiya
1
Je pense aussi que vous devriez donner un exemple.
byxor
Je suppose que ce >>>n'est pas signé, mais pourquoi 7>>32=7? J'ai couru une boucle qui a fait un changement à la fois et j'ai vu qu'après les 32changements, elle est revenue 7. La seule façon pour que cela ait un sens est que pour chaque nombre déplacé, il entre dans un «cercle extérieur». Après les 32quarts de travail, il a retrouvé sa position, mais de toute évidence cela n'a toujours pas de sens. Que se passe-t-il?
Ian Limarta
@IanLimarta Ce n'est pas le cas? Je reçois juste 0. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) Si vous voulez dire pourquoi >>32lui-même retourne la valeur d'origine, voyez ceci .
Moira
Je suis désolé. Je voulais dire pourquoi «7 >>> 32 = 7».
Ian Limarta
40

Le décalage logique vers la droite ( v >>> n) renvoie une valeur dans laquelle les bits vont été décalés vers la droite par ndes positions de bits, et les 0 sont décalés du côté gauche. Pensez à décaler les valeurs 8 bits, écrites en binaire:

01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000

Si nous interprétons les bits comme un entier non négatif non signé, le décalage à droite logique a pour effet de diviser le nombre par la puissance correspondante de 2. Cependant, si le nombre est en représentation à complément à deux, le décalage à droite logique ne divise pas correctement les nombres négatifs . Par exemple, le deuxième décalage à droite ci-dessus décale de 128 à 32 lorsque les bits sont interprétés comme des nombres non signés. Mais il passe de -128 à 32 lorsque, comme c'est généralement le cas en Java, les bits sont interprétés en complément à deux.

Par conséquent, si vous vous déplacez pour diviser par une puissance de deux, vous voulez le décalage arithmétique à droite ( v >> n). Il renvoie une valeur dans laquelle les bits vont été décalés vers la droite par ndes positions binaires, et des copies du bit le plus à gauche de v sont décalées du côté gauche:

01111111 >> 2 = 00011111
10000000 >> 2 = 11100000

Lorsque les bits sont un nombre en représentation du complément à deux, le décalage arithmétique vers la droite a pour effet de diviser par une puissance de deux. Cela fonctionne car le bit le plus à gauche est le bit de signe. La division par une puissance de deux doit conserver le même signe.

andru
la source
38

>>>mettra toujours un 0 dans le bit le plus à gauche, tandis que >>mettra un 1 ou un 0 selon son signe.

corsiKa
la source
10

En savoir plus sur les opérateurs Bitwise et Bit Shift

>>      Signed right shift
>>>     Unsigned right shift

La configuration binaire est donnée par l'opérande de gauche et le nombre de positions à décaler par l'opérande de droite. L'opérateur de décalage à droite non signé >>> décale un zéro dans la position la plus à gauche ,

tandis que la position la plus à gauche après >>dépend de l'extension du signe.

En termes simples, décale>>> toujours un zéro dans la position la plus à gauche tandis que >>décale en fonction du signe du nombre, c'est-à-dire 1 pour le nombre négatif et 0 pour le nombre positif.


Par exemple, essayez avec des nombres négatifs et positifs.

int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));

System.out.println();

c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));

production:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000
Braj
la source
Merci. Je veux juste ajouter un commentaire pour référencer la représentation binaire pour Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 . par exemple System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')):; Integer.MAX_VALUE : 01111111111111111111111111111111; Integer.MIN_VALUE : 10000000000000000000000000000000; -1 : 11111111111111111111111111111111; 0 : 00000000000000000000000000000000; 1 : 00000000000000000000000000000001
Andy Dong
6

L'opérateur logique de décalage à droite ( >>> N) décale les bits vers la droite de N positions, supprimant le bit de signe et remplissant les N bits les plus à gauche par des 0. Par exemple:

-1 (in 32-bit): 11111111111111111111111111111111

après qu'une >>> 1opération devient:

2147483647: 01111111111111111111111111111111

L'opérateur arithmétique de décalage à droite ( >> N) décale également les bits vers la droite de N positions, mais préserve le bit de signe et remplit les N bits les plus à gauche par des 1. Par exemple:

-2 (in 32-bit): 11111111111111111111111111111110

après qu'une >> 1opération devient:

-1: 11111111111111111111111111111111
bigT
la source