>>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.
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.
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.
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.
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=0001111110000000>>>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=0001111110000000>>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.
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));
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:
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ía11111111
, 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ía01111111
.fuente
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 unchar[]
. No está diciendo que achar
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.JLS 15.19 Operadores de turno
Para aclarar las cosas agregando contrapartida positiva
Como es positivo, tanto los cambios con signo como sin signo agregarán 0 al bit más a la izquierda.
Preguntas relacionadas
1 >>> 32 == 1
fuente
Ambos tienen desplazamiento a la derecha, pero
>>>
esunsigned
De la documentación :
fuente
>>>
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 los32
turnos, volvía a funcionar7
. 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 los32
turnos, llegó de alguna manera a su posición, pero obviamente eso todavía no tiene sentido. Que esta pasando?for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));
) Si quiere decir por qué en>>32
sí mismo devuelve el valor original, vea esto .El desplazamiento lógico a la derecha (
v >>> n
) devuelve un valor en el que los bitsv
se han desplazado hacia la derecha porn
posiciones de bit, y los 0 se desplazan desde el lado izquierdo. Considere cambiar los valores de 8 bits, escritos en binario: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 bitsv
se han desplazado a la derecha porn
posiciones de bit, y las copias del bit más a la izquierda de v se desplazan desde el lado izquierdo: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.
fuente
>>>
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.fuente
Lea más sobre los operadores Bitwise y Bit 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.
salida:
fuente
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:después de que una
>>> 1
operación se convierte en: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:después de que una
>> 1
operación se convierte en:fuente