Respuestas:
>>
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
.
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?
String
también podría considerarse como un char[]
. No está diciendo que a char
no es un número; solo dice que es un número sin signo . Creo que ahí es donde está perdido.
>>>
es unsigned-shift; insertará 0. >>
está firmado y extenderá el bit de signo.
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>>s
es posiciones de bitn
desplazadas hacia la derechas
con extensión de signo .El valor de
n>>>s
es posiciones de bitn
desplazadas a la derechas
con 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.
1 >>> 32 == 1
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.
>>>
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 32
turnos, 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 32
turnos, llegó de alguna manera a su posición, pero obviamente eso todavía no tiene sentido. Que esta pasando?
El desplazamiento lógico a la derecha ( v >>> n
) devuelve un valor en el que los bits v
se han desplazado hacia la derecha por n
posiciones 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 v
se han desplazado a la derecha por n
posiciones 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.
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
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
El operador lógico de >>> N
desplazamiento 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 >>> 1
operación se convierte en:
2147483647: 01111111111111111111111111111111
El operador aritmético de >> N
desplazamiento 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 >> 1
operación se convierte en:
-1: 11111111111111111111111111111111