Diferencia entre >>> y >>


Respuestas:


408

>>es el desplazamiento aritmético a la derecha, el >>>desplazamiento lógico a la derecha.

En un cambio aritmético, el bit de signo se extiende para preservar la firma del número.

Por ejemplo: -2 representados en 8 bits sería 11111110(porque el bit más significativo tiene un peso negativo). Desplazándolo a la derecha un bit usando el desplazamiento aritmético te daría 11111111, o -1. Sin embargo, el desplazamiento lógico a la derecha no le importa que el valor pueda representar un número con signo; simplemente mueve todo a la derecha y completa desde la izquierda con 0s. Cambiar nuestro -2 a la derecha un bit usando el desplazamiento lógico daría 01111111.


8
Si bien estoy de acuerdo y aprecio que los cambios aritméticos se pueden usar para multiplicar números con signo 2^k, me parece extraño que esta sea la respuesta de todos. Una cadena de bits no es un número, y >>siempre se puede usar en cualquier cadena de bits: siempre hace lo mismo independientemente del papel que desempeñe la cadena de bits y de si tiene un concepto de 'signo'. ¿Estaría bien extender su excelente respuesta con una discusión del caso cuando su operando no se interpreta como un número firmado? ¿Mi queja tiene sentido?
Ziggy

11
¿Por qué dices que una cadena de bits no es un número? ¿Diría que una secuencia de dígitos decimales no es un número?
danben

44
@danben Discutir si es o no un número solo tiene sentido si lo vincula a un contexto. Si Internet es solo electricidad, entonces estoy de acuerdo en que un String es solo un número.
bvdb

1
@danben pero en realidad, creo que a lo que Ziggy realmente se refería (en mi humilde opinión), es que a Stringtambién podría considerarse como un char[]. No está diciendo que a charno es un número; solo dice que es un número sin signo . Creo que ahí es donde está perdido.
bvdb

55
@Ziggy tiene razón: no todas las cadenas de bits son un número, y no todas las secuencias de dígitos decimales son un número. Por ejemplo: los números de teléfono, los códigos postales (en muchos países), etc. son cadenas de dígitos decimales, pero no tiene sentido sumarlos, restarlos o multiplicarlos, por lo que en realidad no son números. Resultan ser cadenas de dígitos decimales, pero deben tratarse como cadenas de caracteres. (Los códigos postales en Canadá y el Reino Unido contienen letras y dígitos.)
jcsahnwaldt dice GoFundMonica

102

>>>es unsigned-shift; insertará 0. >>está firmado y extenderá el bit de signo.

JLS 15.19 Operadores de turno

Los operadores de desplazamiento incluyen desplazamiento a la izquierda <<, desplazamiento a la >>derecha con signo y desplazamiento a la derecha sin signo >>>.

El valor de n>>ses posiciones de bit ndesplazadas hacia la derecha scon extensión de signo .

El valor de n>>>ses posiciones de bit ndesplazadas a la derecha scon extensión cero .

    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"

Para aclarar las cosas agregando contrapartida positiva

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"

Como es positivo, tanto los cambios con signo como sin signo agregarán 0 al bit más a la izquierda.

Preguntas relacionadas


Sin sus ejemplos, no lo entendería.
mr5

47

Ambos tienen desplazamiento a la derecha, pero >>>esunsigned

De la documentación :

El operador de desplazamiento a la derecha sin signo ">>>" desplaza un cero a la posición más a la izquierda, mientras que la posición más a la izquierda después de ">>" depende de la extensión del signo.


12
¿Puedes explicarlo con un ejemplo
Kasun Siyambalapitiya

1
También creo que deberías dar un ejemplo.
byxor

Supongo que >>>no está firmado, pero ¿por qué 7>>32=7? Ejecuté un bucle que hacía un turno a la vez y vi que después de los 32turnos, volvía a funcionar 7. La única forma en que esto podría tener sentido es que para cada número desplazado, ingrese un "círculo externo". Después de los 32turnos, llegó de alguna manera a su posición, pero obviamente eso todavía no tiene sentido. Que esta pasando?
Ian Limarta

@IanLimarta ¿No es así? Acabo de obtener 0. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) Si quiere decir por qué en >>32sí mismo devuelve el valor original, vea esto .
Moira

Lo siento. Quise decir por qué '7 >>> 32 = 7'.
Ian Limarta

40

El desplazamiento lógico a la derecha ( v >>> n) devuelve un valor en el que los bits vse han desplazado hacia la derecha por nposiciones de bit, y los 0 se desplazan desde el lado izquierdo. Considere cambiar los valores de 8 bits, escritos en binario:

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

Si interpretamos los bits como un entero no negativo sin signo, el desplazamiento lógico a la derecha tiene el efecto de dividir el número por la potencia correspondiente de 2. Sin embargo, si el número está en representación de complemento a dos, el desplazamiento lógico a la derecha no divide correctamente los números negativos. . Por ejemplo, el segundo desplazamiento a la derecha anterior desplaza 128 a 32 cuando los bits se interpretan como números sin signo. Pero cambia -128 a 32 cuando, como es típico en Java, los bits se interpretan en complemento a dos.

Por lo tanto, si está cambiando para dividir por una potencia de dos, desea el desplazamiento aritmético a la derecha ( v >> n). Devuelve un valor en el que los bits vse han desplazado a la derecha por nposiciones de bit, y las copias del bit más a la izquierda de v se desplazan desde el lado izquierdo:

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

Cuando los bits son un número en representación de complemento a dos, el desplazamiento aritmético a la derecha tiene el efecto de dividir por una potencia de dos. Esto funciona porque el bit más a la izquierda es el bit de signo. Dividir por un poder de dos debe mantener el signo igual.


38

>>>siempre pondrá un 0 en el bit más a la izquierda, mientras >>que pondrá un 1 o un 0 dependiendo de cuál sea su signo.


10

Lea más sobre los operadores Bitwise y Bit Shift

>>      Signed right shift
>>>     Unsigned right shift

El patrón de bits viene dado por el operando de la izquierda, y el número de posiciones para desplazarse por el operando de la derecha. El operador de >>> desplazamiento a la derecha sin signo desplaza un cero a la posición más a la izquierda ,

mientras que la posición más a la izquierda >>depende de la extensión del signo.

En palabras simples, >>>siempre cambia un cero a la posición más a la izquierda, mientras que los >>cambios se basan en el signo del número, es decir, 1 para el número negativo y 0 para el número positivo.


Por ejemplo, intente con números negativos y positivos.

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));

salida:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000

Gracias. Solo quiero agregar un comentario para hacer referencia a la representación de bits para Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 . por ejemplo 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

El operador lógico de >>> Ndesplazamiento a la derecha ( ) desplaza bits a la derecha por N posiciones, descartando el bit de signo y rellenando los N bits más a la izquierda con 0. Por ejemplo:

-1 (in 32-bit): 11111111111111111111111111111111

después de que una >>> 1operación se convierte en:

2147483647: 01111111111111111111111111111111

El operador aritmético de >> Ndesplazamiento a la derecha ( ) también desplaza bits a la derecha por N posiciones, pero conserva el bit de signo y rellena los N bits más a la izquierda con 1. Por ejemplo:

-2 (in 32-bit): 11111111111111111111111111111110

después de que una >> 1operación se convierte en:

-1: 11111111111111111111111111111111
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.