in

agnóstico del lenguaje – ¿Qué son los operadores de desplazamiento de bits (bit-shift) y cómo funcionan?

apple touch icon@2

Los operadores de cambio de bits hacen exactamente lo que su nombre indica. Cambian bits. Aquí hay una breve (o no tan breve) introducción a los diferentes operadores de turnos.

Los operadores

  • >> es el operador de desplazamiento a la derecha aritmético (o con signo).
  • >>> es el operador de desplazamiento a la derecha lógico (o sin firmar).
  • << es el operador de desplazamiento a la izquierda y satisface las necesidades de los desplazamientos tanto lógicos como aritméticos.

Todos estos operadores se pueden aplicar a valores enteros (int, long, posiblemente short y byte o char). En algunos lenguajes, aplicar los operadores de turno a cualquier tipo de datos menor que int cambia automáticamente el tamaño del operando para que sea un int.

Tenga en cuenta que <<< no es un operador, porque sería redundante.

También tenga en cuenta que C y C ++ no distinguen entre los operadores de turno correctos. Proporcionan solo el >> operador, y el comportamiento de desplazamiento a la derecha se define por implementación para tipos firmados. El resto de la respuesta usa los operadores C # / Java.

(En todas las implementaciones principales de C y C ++, incluidas GCC y Clang / LLVM, >> en tipos con signo es aritmética. Algunos códigos asumen esto, pero no es algo que garantice el estándar. No es indefinido, aunque; el estándar requiere implementaciones para definirlo de una forma u otra. Sin embargo, los desplazamientos a la izquierda de números con signo negativo es comportamiento indefinido (desbordamiento de enteros con signo). Entonces, a menos que necesite un cambio aritmético a la derecha, generalmente es una buena idea hacer su cambio de bits con tipos sin firmar).


Desplazamiento a la izquierda (<<)

Los enteros se almacenan, en la memoria, como una serie de bits. Por ejemplo, el número 6 almacenado como 32 bits int sería:

00000000 00000000 00000000 00000110

Desplazando este patrón de bits a la izquierda una posición (6 << 1) resultaría en el número 12:

00000000 00000000 00000000 00001100

Como puede ver, los dígitos se han desplazado una posición hacia la izquierda y el último dígito de la derecha se ha llenado con un cero. También puedes notar que desplazarse a la izquierda es equivalente a multiplicar por potencias de 2. Entonces 6 << 1 es equivalente a 6 * 2, y 6 << 3 es equivalente a 6 * 8. Un buen compilador de optimización reemplazará las multiplicaciones con cambios cuando sea posible.

Cambio no circular

Tenga en cuenta que estos son no turnos circulares. Desplazando este valor a la izquierda una posición (3,758,096,384 << 1):

11100000 00000000 00000000 00000000

da como resultado 3.221.225.472:

11000000 00000000 00000000 00000000

El dígito que se desplaza «al final» se pierde. No envuelve.


Desplazamiento lógico a la derecha (>>>)

Un desplazamiento lógico a la derecha es el inverso al desplazamiento a la izquierda. En lugar de mover los bits hacia la izquierda, simplemente se mueven hacia la derecha. Por ejemplo, cambiando el número 12:

00000000 00000000 00000000 00001100

a la derecha en una posición (12 >>> 1) recuperará nuestros 6 originales:

00000000 00000000 00000000 00000110

Entonces vemos que desplazarse hacia la derecha es equivalente a la división por potencias de 2.

Los pedazos perdidos se han ido

Sin embargo, un cambio no puede recuperar bits «perdidos». Por ejemplo, si cambiamos este patrón:

00111000 00000000 00000000 00000110

a la izquierda 4 posiciones (939,524,102 << 4), obtenemos 2,147,483,744:

10000000 00000000 00000000 01100000

y luego retrocediendo ((939,524,102 << 4) >>> 4) obtenemos 134,217,734:

00001000 00000000 00000000 00000110

No podemos recuperar nuestro valor original una vez que hemos perdido bits.


El desplazamiento aritmético a la derecha es exactamente igual al desplazamiento lógico a la derecha, excepto que en lugar de rellenar con cero, rellena con el bit más significativo. Esto se debe a que el bit más significativo es el firmar bit, o el bit que distingue números positivos y negativos. Al rellenar con el bit más significativo, el desplazamiento aritmético a la derecha conserva el signo.

Por ejemplo, si interpretamos este patrón de bits como un número negativo:

10000000 00000000 00000000 01100000

tenemos el número -2,147,483,552. Cambiar esto a la derecha 4 posiciones con el cambio aritmético (-2,147,483,552 >> 4) nos daría:

11111000 00000000 00000000 00000110

o el número -134,217,722.

Entonces vemos que hemos conservado el signo de nuestros números negativos usando el desplazamiento aritmético a la derecha, en lugar del desplazamiento lógico a la derecha. Y una vez más, vemos que estamos realizando una división por potencias de 2.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Python – Pila

verilog full adder

Sumador completo de Verilog – javatpoint