Битовые операции

В этом разделе показано, как использовать битовые операции в MATLAB ® для манипулирования битами чисел. Работа с битами напрямую поддерживается большинством современных центральных процессоров. Во многих случаях манипулирование битами числа таким образом быстрее, чем выполнение арифметических операций, таких как деление или умножение.

Числовые представления

Любое число может быть представлено с битами (также известными как двоичные цифры). Двоичная, или база 2, форма числа содержит 1с и 0с, чтобы указать, какие степени 2 присутствуют в числе. Для примера 8-битная двоичная форма 7 является

00000111

Набор из 8 бит также называется 1 байт. В двоичных представлениях биты отсчитываются справа налево, поэтому первый бит в этом представлении равен 1. Это число представляет 7, потому что

22+21+20=7.

Когда вы вводите числа в MATLAB, это предполагает, что числа являются двойной точностью (64-битное двоичное представление). Однако можно также задать числа с одной точностью (32-битное двоичное представление) и целые числа (со знаком или без знака, от 8 до 64 бит). Для примера самый эффективный способ памяти для хранения числа 7 - это 8-битное беззнаковое целое число:

a = uint8(7)
a = uint8
    7

Можно даже задать двоичную форму непосредственно с помощью префикса 0b далее указываются двоичные цифры (для получения дополнительной информации см. Шестнадцатеричные и двоичные значения). MATLAB сохраняет число в целом формате с наименьшим количеством бит. Вместо того, чтобы указывать все биты, необходимо задать только самый левый 1 и все цифры справа от него. Биты слева от этого бита тривиально равны нулю. Итак, число 7:

b = 0b111
b = uint8
    7

MATLAB хранит отрицательные целые числа, используя дополнение двух. Для примера рассмотрим 8-битное целое число со знаком -8. Чтобы найти битовый шаблон двух комплементов для этого числа:

  1. Начните с битового шаблона положительной версии числа, 8: 00001000.

  2. Затем переверните все биты: 11110111.

  3. Наконец, добавьте 1 к результату: 11111000.

Результат, 11111000, - битовый шаблон для -8:

n = 0b11111000s8
n = int8
    -8

MATLAB не отображает двоичный формат чисел. Для этого можно использовать dec2bin функция, которая возвращает вектор символов из двоичных цифр для положительных целых чисел. Снова, эта функция возвращает только цифры, которые не являются тривиально нулем.

dec2bin(b)
ans = 
'111'

Можно использовать bin2dec для переключения между этими двумя форматами. Для примера можно преобразовать двоичные цифры 10110101 для десятичного формата с помощью команд

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

The cast и typecast функции также полезны для переключения между различными типами данных. Эти функции похожи, но отличаются они тем, как они относятся к базовому хранению числа:

  • cast - Изменяет базовый тип данных переменной.

  • typecast - Преобразует типы данных, не меняя базовые биты.

Поскольку MATLAB не отображает цифры двоичного числа непосредственно, вы должны обратить внимание на типы данных, когда вы работаете с битовыми операциями. Некоторые функции возвращают двоичные цифры как вектор символов (dec2bin), некоторые возвращают десятичное число (bitand), а другие возвращают вектор самих бит (bitget).

Битовая маскировка с помощью логических операторов

MATLAB имеет несколько функций, которые позволяют вам выполнять логические операции над битами двух двоичных представлений чисел равной длины, известных как битовая маскировка:

  • bitand - Если обе цифры равны 1, то получившаяся цифра также равна 1. В противном случае получившаяся цифра равняется 0.

  • bitor - Если любая цифра равна 1, то получившаяся цифра также равна 1. В противном случае получившаяся цифра равняется 0.

  • bitxor - Если цифры отличаются, то получившаяся цифра равна 1. В противном случае получившаяся цифра равняется 0.

В дополнение к этим функциям, битовое дополнение доступно с bitcmp, но это унарная операция, которая переворачивает биты только одним числом за раз.

Одним из способов маскирования битов является запрос состояния конкретного бита. Для примера, если вы используете битовую операцию AND с двоичным числом 00001000можно запросить состояние четвертого бита. Затем можно переместить этот бит в первое положение, чтобы MATLAB вернул 0 или 1 (следующий раздел описывает сдвиг бита более подробно).

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

Битовые операции могут иметь удивительные приложения. Для примера рассмотрим 8-битное двоичное представление числа n=8:

00001000

8 является степенью 2, поэтому его двоичное представление содержит одну единицу 1. Теперь рассмотрим число (n-1)=7:

00000111

Путем вычитания 1 все биты, начинающиеся с самого правого 1, поворачиваются. В результате, когда n - степень 2, соответствующие цифры n и (n-1) всегда разные, и Bit-wise AND возвращает нуль.

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

Однако когда n не является степенью 2, тогда самый правый 1 для 20 бит, так n и (n-1) иметь все те же биты, кроме 20 бит. В этом случае bitwise AND возвращает ненулевое число.

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

Эта операция предлагает простую функцию, которая работает с битами заданного входного числа, чтобы проверить, является ли число степенью 2:

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

Использование оператора короткой схемы && проверяет, чтобы убедиться, что n не равен нулю. Если это так, то функции не нужно вычислять bitand(n,n-1) знать, что правильный ответ false.

Сдвигающие биты

Поскольку битовые логические операции сравнивают соответствующие биты в двух числах, полезно иметь возможность перемещать биты вокруг, чтобы изменить, какие биты сравниваются. Можно использовать bitshift для выполнения этой операции:

  • bitshift(A,N) сдвигает биты A налево по N цифр. Это эквивалентно умножению A около 2N.

  • bitshift(A,-N) сдвигает биты A направо по N цифр. Это эквивалентно делению A около 2N.

Эти операции иногда записываются A<<N (смена влево) и A>>N (правый сдвиг), но MATLAB не использует << и >> операторы для этой цели.

Когда биты числа сдвигаются, некоторые биты падают с конца числа, и 0s или 1s вводятся для заполнения вновь созданного пространства. Когда вы смещаете биты налево, биты заполняются справа; когда вы смещаете биты вправо, биты заполняются слева.

Для примера, если вы сдвигаете биты числа 8 (двоичный: 1000) справа на одну цифру вы получаете 4 (двоичный: 100).

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

Точно так же, если вы сдвинете число 15 (двоичный: 1111) налево двумя цифрами, вы получаете 60 (двоичный: 111100).

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

Когда вы сдвигаете биты отрицательного числа, bitshift сохраняет бит со знаком. Для примера, если вы сдвигаете целое число со знаком -3 (двоичный: 11111101) справа на 2 цифры вы получаете -1 (двоичный: 11111111). В этих случаях bitshift заполняет слева 1s, а не 0с.

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

Запись бит

Можно использовать bitset функция для изменения бит в значении. Для примера смените первый бит числа 8 на 1 (который добавляет 1 к числу):

bitset(8,1)
ans = 9

По умолчанию bitset переворачивает биты на on или 1. Вы можете опционально использовать третий входной параметр, чтобы задать значение бита.

bitset не меняет несколько биты сразу, поэтому нужно использовать for цикл для изменения нескольких бит. Поэтому изменяемые биты могут быть либо последовательными, либо неконсективными. Для примера измените первые два бита двоичного числа 1000:

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

Другое распространенное использование bitset преобразует вектор двоичных цифр в десятичный формат. Например, используйте цикл, чтобы задать отдельные биты целого числа 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'

Чтение последовательных бит

Другое использование перемены битов состоит в том, чтобы изолировать последовательные секции бит. Для примера прочитайте последние четыре бита в 16-битном номере 0110000010100000. Напомним, что последние четыре бита находятся слева от двоичного представления.

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

Чтобы изолировать последовательные биты в середине числа, можно объединить использование сдвига битов с логической маскировкой. Например, чтобы извлечь 13-й и 14-й биты, можно сместить биты вправо на 12 и затем замаскировать получившиеся четыре бита 0011. Потому что входы для bitand должен быть таким же целым типом данных, можно задать 0011 как беззнаковое 16-битное целое число с 0b11u16. Без -u16 суффикс, MATLAB сохраняет число как беззнаковое 8-битное целое число.

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

Другой способ чтения последовательных бит - это bitget, который считывает указанные биты из числа. Можно использовать обозначение двоеточия, чтобы задать несколько последовательные биты для чтения. Например, считайте последние 8 биты n.

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

   0   1   1   0   0   0   0   0   1

Чтение неконсективных бит

Можно также использовать bitget считывать биты из числа, когда биты не находятся рядом друг с другом. Например, считайте 5-й, 8-й и 14-й биты из n.

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

   1   1   0

См. также

| | | | | |

Похожие темы