Main Content

Operaciones bit por bit

Este tema muestra cómo utilizar operaciones bit por bit en MATLAB® para manipular los bits de los números. Las operaciones en bits son directamente compatibles con la mayoría de CPU modernas. En muchos casos, manipular los bits de un número de esta manera es más rápido que realizar operaciones aritméticas como la división o la multiplicación.

Representaciones de números

Cualquier número se puede representar con bits (también conocidos como dígitos binarios). La forma binaria, o en base 2, de un número contiene unos (1) y ceros (0) para indicar las potencias de dos (2) presentes en un número. Por ejemplo, la forma binaria en 8 bits de 7 es

00000111

Un conjunto de 8 bits también se conoce como 1 byte. En las representaciones binarias, los bits se cuentan de derecha a izquierda, de forma que el primer bit de esta representación es un 1. Este número representa el 7 porque

22+21+20=7.

Al introducir números en MATLAB, el sistema asume que los números son de precisión doble (una representación binaria de 64 bits). Sin embargo, también puede especificar números de precisión simple (representación binaria de 32 bits) y números enteros (con signo o sin signo, de 8 a 64 bits). Por ejemplo, la manera más eficiente para la memoria de guardar el número 7 es con un número entero sin signo de 8 bits:

a = uint8(7)
a = uint8
    7

Incluso puede especificar la forma binaria utilizando directamente el prefijo 0b seguido de los dígitos binarios (para obtener más información, consulte Valores binarios y hexadecimales). MATLAB guarda el número en formato de número entero con el menor número de bits. En lugar de especificar todos los bits, especifique solo el 1 que se sitúa más a la izquierda y todos los dígitos que quedan a la derecha. Los bits que quedan a la izquierda de dicho bit son ceros sin valor. Por lo tanto, el número 7 es:

b = 0b111
b = uint8
    7

MATLAB guarda los números enteros negativos con el complemento de dos. Por ejemplo, considere el número entero con signo -8 de 8 bits. Para encontrar el patrón de bits del complemento de dos de este número:

  1. Comience con el patrón de bits de la versión positiva del número, 8: 00001000.

  2. Después, invierta el resto de bits: 11110111.

  3. Por último, añada 1 al resultado: 11111000.

El resultado, 11111000, es el patrón de bits de -8:

n = 0b11111000s8
n = int8
    -8

MATLAB no muestra de forma nativa el formato binario de los números. Para ello, puede utilizar la función dec2bin, que devuelve un vector de caracteres de dígitos binarios de números enteros positivos. De nuevo, esta función solo devuelve los dígitos que no son cero sin valor.

dec2bin(b)
ans = 
'111'

Puede utilizar bin2dec para cambiar entre ambos formatos. Por ejemplo, puede convertir los dígitos binarios 10110101 a formato decimal con los comandos

data = [1 0 1 1 0 1 0 1];
dec = bin2dec(num2str(data))
dec = 181

Las funciones cast y typecast también resultan útiles para cambiar entre distintos tipos de datos. Estas funciones son similares, pero difieren en el modo en que tratan el almacenamiento subyacente del número:

  • cast — Cambia el tipo de datos subyacentes de una variable.

  • typecast — Convierte tipos de datos sin cambiar los bits subyacentes.

Ya que MATLAB no muestra los dígitos en números binarios directamente, debe prestar atención a los tipos de datos al trabajar con operaciones bit por bit. Algunas funciones devuelven los dígitos binarios como un vector de caracteres (dec2bin), otras devuelven el número decimal (bitand) y otras devuelven un vector de los mismos bits (bitget).

Enmascaramiento de bits con operadores lógicos

MATLAB cuenta con varias funciones que le permiten efectuar operaciones lógicas en los bits de dos representaciones binarias de números de igual longitud, conocidas como enmascaramiento de bits:

  • bitand — Si ambos dígitos son 1, el dígito resultante también es un 1. De lo contrario, el dígito resultante es 0.

  • bitor — Si uno de los dos dígitos es 1, el dígito resultante es también un 1. De lo contrario, el dígito resultante es 0.

  • bitxor — Si los dígitos son distintos, el dígito resultante es un 1. De lo contrario, el dígito resultante es 0.

Además de estas funciones, el complemento de bit por bit está disponible con bitcmp, pero se trata de una operación unaria que invierte los bits de un solo número de una vez.

Un uso del enmascaramiento de bits es consultar el estado de un bit en concreto. Por ejemplo, si utiliza una operación AND bit por bit con el número binario 00001000, puede consultar el estado del cuarto bit. Después, puede desplazar dicho bit a la primera posición, de forma que MATLAB devuelva un 0 o un 1 (la siguiente sección describe el desplazamiento de bits con mayor detenimiento).

n = 0b10111001;
n4 = bitand(n,0b1000);
n4 = bitshift(n4,-3)
n4 = uint8
    1

Las operaciones bit por bit pueden tener aplicaciones sorprendentes. Por ejemplo, considere la representación binaria de 8 bits del número n=8:

00001000

8 es una potencia de 2, por lo que su representación binaria contiene solo un 1. Ahora considere el número (n-1)=7:

00000111

Restando 1, se invierten todos los bits a partir del 1 situado más a la derecha. Como resultado, cuando n es una potencia de 2, los dígitos correspondientes de n y (n-1) son siempre distintos y el AND bit por bit devuelve un cero.

n = 0b1000;
bitand(n,n-1)
ans = uint8
    0

Sin embargo, cuando n no es una potencia de 2, el 1 situado más a la derecha es para el bit 20, de modo que n y (n-1) tienen los mismos bits excepto el bit 20. En este caso, el AND bit por bit devuelve un número distinto de cero.

n = 0b101;
bitand(n,n-1)
ans = uint8
    4

Esta operación propone una función simple que opera en los bits de un número de entrada determinado para comprobar si el número es una potencia de 2:

function tf = isPowerOfTwo(n)
  tf = n && ~bitand(n,n-1);
end

El uso del operador AND con cortocircuito && comprueba que n no es cero. Si lo es, la función no necesita calcular bitand(n,n-1) para saber que la respuesta correcta es false.

Desplazamiento de bits

Debido a que las operaciones lógicas bit por bit comparan los bits correspondientes de dos números, resulta útil poder mover los bits para cambiar los bits que se comparan. Puede utilizar bitshift para llevar a cabo esta operación:

  • bitshift(A,N) desplaza los bits de A a la izquierda N dígitos. Esto equivale a multiplicar A por 2N.

  • bitshift(A,-N) desplaza los bits de A a la derecha N dígitos. Esto equivale a dividir A por 2N.

En ocasiones, estas operaciones se encuentran escritas como A<<N (desplazamiento a la izquierda) y A>>N (desplazamiento a la derecha), pero MATLAB no utiliza los operadores << y >> con este fin.

Cuando se desplazan los bits de un número, algunos bits desaparecen del final del número y se introducen 0 o 1 para rellenar el espacio recién creado. Cuando se desplazan bits a la izquierda, los bits se rellenan a la derecha y viceversa.

Por ejemplo, si desplaza los bits del número 8 (binario: 1000) a la derecha un dígito, obtiene un 4 (binario: 100).

n = 0b1000;
bitshift(n,-1)
ans = uint8
    4

De forma similar, si desplaza el número 15 (binario: 1111) a la izquierda dos dígitos, obtiene un 60 (binario: 111100).

n = 0b1111;
bitshift(15,2)
ans = 60

Al desplazar los bits de un número negativo, bitshift conserva el bit con signo. Por ejemplo, si desplaza el número entero con signo -3 (binario: 11111101) a la derecha dos dígitos, obtiene un -1 (binario: 11111111). En estos casos, bitshift rellena a la izquierda con 1 en lugar de con 0.

n = 0b11111101s8;
bitshift(n,-2)
ans = int8
    -1

Escritura de bits

Puede utilizar la función bitset para cambiar los bits de un número. Por ejemplo, cambie el primer bit del número 8 a un 1 (que añade 1 al número):

bitset(8,1)
ans = 9

De manera predeterminada, bitset invierte los bits a activado o 1. De manera opcional, puede utilizar el tercer argumento de entrada para especificar el valor del bit.

bitset no cambia varios bits a la vez, por lo que ha de utilizar un bucle for para cambiar varios bits. Por consiguiente, los bits que cambia pueden ser consecutivos o no. Por ejemplo, cambie los primeros dos bits del número binario 1000:

bits = [1 2];
c = 0b1000;
for k = 1:numel(bits)
    c = bitset(c,bits(k));
end
dec2bin(c)
ans = 
'1011'

Otro uso habitual de bitset es convertir un vector de dígitos binarios a formato decimal. Por ejemplo, utilice un bucle para establecer cada uno de los bits del número entero 11001101.

data = [1 1 0 0 1 1 0 1];
n = length(data);
dec = 0b0u8;
for k = 1:n
    dec = bitset(dec,n+1-k,data(k));
end
dec
dec = uint8
    205
dec2bin(dec)
ans = 
'11001101'

Lectura de bits consecutivos

Otro uso del desplazamiento de bits es aislar secciones de bits consecutivas. Por ejemplo, lea los últimos cuatro bits del número de 16 bits 0110000010100000. Recuerde que los últimos cuatro bits se encuentran a la izquierda de la representación binaria.

n = 0b0110000010100000;
dec2bin(bitshift(n,-12))
ans = 
'110'

Para aislar bits consecutivos en mitad del número, puede combinar el uso del desplazamiento de bits con el enmascaramiento lógico. Por ejemplo, para extraer los bits número 13 y 14, puede desplazar los bits 12 posiciones a la derecha y, después, enmascarar los cuatro bits resultantes con 0011. Ya que los valores de entrada de bitand deben ser del mismo tipo de datos de números enteros, puede especificar 0011 como un número entero sin signo de 16 bits con 0b11u16. Sin el sufijo -u16, MATLAB guarda el número como un número entero sin signo de 8 bits.

m = 0b11u16;
dec2bin(bitand(bitshift(n,-12),m))
ans = 
'10'

Otra forma de leer bits consecutivos es con bitget, que lee bits específicos de un número. Puede utilizar la notación de dos puntos para especificar varios bits consecutivos que se deben leer. Por ejemplo, lea los últimos 8 bits de n.

bitget(n,16:-1:8)
ans = 1x9 uint16 row vector

   0   1   1   0   0   0   0   0   1

Lectura de bits no consecutivos

También puede utilizar bitget para leer los bits de un número cuando dichos bits no están uno junto a otro. Por ejemplo, lea los bits número 5, 8 y 14 de n.

bits = [14 8 5];
bitget(n,bits)
ans = 1x3 uint16 row vector

   1   1   0

Consulte también

| | | | | |

Temas relacionados