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.