ejemplo - Java: desplazamiento a la derecha en número negativo
text box java (3)
Debido a que en Java no hay tipos de datos sin signo, existen dos tipos de cambios a la derecha: desplazamiento aritmético >>
y cambio lógico >>>
. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
El cambio aritmético >>
mantendrá el bit de signo.
El cambio sin signo >>>
no mantendrá el bit de signo (llenando así 0
s).
(imágenes de Wikipedia)
Por cierto, tanto el desplazamiento aritmético a la izquierda como el desplazamiento a la izquierda lógico tienen el mismo resultado, por lo que solo hay un desplazamiento a la izquierda <<
.
Estoy muy confundido sobre la operación de cambio a la derecha en el número negativo, aquí está el código.
int n = -15;
System.out.println(Integer.toBinaryString(n));
int mask = n >> 31;
System.out.println(Integer.toBinaryString(mask));
Y el resultado es:
11111111111111111111111111110001
11111111111111111111111111111111
¿Por qué derecho cambiar un número negativo por 31, no 1 (el bit de signo)?
Operator >>
called Signed right shift , cambia todos los bits a la derecha un número específico de veces. Importante es >>
llena el bit de signo más a la izquierda (Bit MSB más significativo) al bit más a la izquierda después del turno. Esto se denomina extensión de signo y sirve para conservar el signo de los números negativos cuando los desplaza hacia la derecha.
A continuación se muestra mi representación esquemática con un ejemplo para mostrar cómo funciona esto (para un byte):
Ejemplo:
i = -5 >> 3; shift bits right three time
La forma de complemento de cinco en dos es 1111 1011
Representación de la memoria:
MSB
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
7 6 5 4 3 2 1 0
^ This seventh, the left most bit is SIGN bit
Y a continuación, ¿cómo funciona? Cuando lo haces -5 >> 3
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
| / /
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
Aviso: los tres bits más a la izquierda son uno porque en cada bit de signo de cambio se conserva y cada bit también es correcto. He escrito que el signo se propaga porque todos estos tres bits se deben a un signo (pero no a datos).
También debido a tres cambios a la derecha, la mayoría de los tres bits son pérdidas.
Los bits entre las dos flechas derechas están expuestos desde bits anteriores en -5
.
Creo que sería bueno si escribo un ejemplo para un número positivo también. El siguiente ejemplo es 5 >> 3
y cinco es un byte es 0000 0101
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
+----+----+----+---+---+---+---+---+
| / /
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
Ver de nuevo Escribo El signo se propaga , Así que más a la izquierda se deben firmar tres ceros para firmar el bit.
Entonces, esto es lo que el operador >>
Signed right shift hace, conserva el signo del operando izquierdo.
[tu respuesta]
En su código, se desplaza -15
a la derecha durante 31
veces usando el operador >>
, de modo que se liberan los 31
bits más a la derecha y los resultados son todos los bits 1
que en realidad son -1
en magnitud.
¿Notan que de esta manera -1 >> n
es equivalente a no una declaración.
Creo que si uno hace i = -1 >> n
debería ser optimizado a i = -1
por los compiladores de Java, pero eso es diferente
A continuación, sería interesante saber que en Java hay disponible un operador de desplazamiento a la derecha más >>>
llamado Unsigned Right Shift . Y funciona lógicamente y llena cero desde la izquierda para cada operación de cambio. Por lo tanto, en cada cambio a la derecha, siempre obtiene un bit Cero en la posición más a la izquierda si usa el operador >>>
desplazamiento a la derecha sin signo para los números Negativo y Positivo.
Ejemplo:
i = -5 >>> 3; Unsigned shift bits right three time
Y debajo está mi diagrama que demuestra cómo funciona la expresión -5 >>> 3
?
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
| / /
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+---+---+---+---+---+
(______________)
These zeros
are inserted
Y pueden notar: esta vez no escribo ese signo, los bits se propagan, pero en realidad >>>
operador inserta ceros. Por lo tanto, >>>
no conserva el signo, sino que realiza el desplazamiento lógico a la derecha.
En mi conocimiento, el desplazamiento a la derecha sin signo es útil en VDU (programación de gráficos), aunque no lo he usado, pero lo he leído en algún lugar del pasado.
Le sugiero que lea esto: la diferencia entre >>> y >> : >>
es un desplazamiento aritmético correcto, >>>
es un cambio lógico correcto.
Editar :
Algo interesante acerca del operador del operador sin signo de la derecha >>>
.
El operador de desplazamiento a la derecha sin signo
>>>
produce un valor puro que es su operando izquierdo desplazado a la derecha con cero0
extensión por el número de bits especificado por su operando de la derecha.Como
>>
y<<
, operador>>>
, el operador nunca lanza una excepción.El tipo de cada operando del operador de desplazamiento a la derecha sin signo debe ser un tipo de datos entero o se produce un error de tiempo de compilación.
El operador
>>>
puede realizar conversiones de tipo en sus operandos; a diferencia de los operadores binarios aritméticos, cada operando se convierte de forma independiente. Si el tipo de un operando es byte, short o char, ese operando se convierte en int antes de que se calcule el valor del operador.El tipo de valor producido por el operador de desplazamiento a la derecha sin signo es el tipo de su operando izquierdo.
LEFT_OPERAND >>> RHIGT_OPERAND
Si el tipo convertido del operando izquierdo es int, solo se utilizan los cinco bits menos significativos del valor del operando derecho como la distancia de desplazamiento. ( eso es 2 5 = 32 bits = número de bit en int )
Entonces, la distancia de cambio está en el rango de 0 a 31.Aquí, el valor producido por
r >>> s
es el mismo que:s==0 ? r : (r >> s) & ~(-1<<(32-s))
Si el tipo del operando izquierdo es largo, entonces solo se utilizan los seis bits menos significativos del valor del operando derecho como la distancia de desplazamiento ( es decir 2 5 = 64 bits = número de bit en largo )
Aquí, el valor producido por
r >>> s
es el mismo que el siguiente:s==0 ? r : (r >> s) & ~(-1<<(64-s))
Una referencia interesante: [Capítulo 4] 4.7 Operadores de cambio
Porque >> se define como un desplazamiento aritmético a la derecha, que preserva el signo. Para obtener el efecto que espera, use un desplazamiento lógico a la derecha, el operador >>>.