В этом разделе показано, как использовать битовые операции в MATLAB ® для управления битами чисел. Работа с битами напрямую поддерживается большинством современных ЦП. Во многих случаях манипулирование битами числа таким образом быстрее, чем выполнение арифметических операций, таких как деление или умножение.
Любое число может быть представлено битами (также известными как двоичные цифры). Двоичная, или базовая 2, форма числа содержит 1 s и 0 s, чтобы указать, какие степени 2 присутствуют в числе. Например, 8-разрядная двоичная форма 7
00000111
Коллекция из 8 битов также называется 1 байт. В двоичных представлениях биты отсчитываются справа налево, поэтому первый бит в этом представлении равен 1. Это число представляет 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. Чтобы найти битовый шаблон дополнения для этого числа:
Начните с битового шаблона положительной версии числа, 8: 00001000.
Затем переверните все биты: 11110111.
Наконец, добавьте 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
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-разрядное двоичное представление числа 8:
00001000
8 является степенью 2, поэтому его двоичное представление содержит один 1. Теперь рассмотрим число 7:
00000111
Вычитая 1, все биты, начинающиеся с самого правого 1, переворачиваются. В результате, когда является степенью 2, соответствующие цифры и всегда различны, и битовое И возвращает ноль.
n = 0b1000; bitand(n,n-1)
ans = uint8
0
Однако, когда не является степенью 2, то самый правый 1 является для бит, поэтому и имеют все те же биты, за исключением бит. В этом случае побитовое И возвращает ненулевое число.
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 по .
bitshift(A,-N) сдвигает биты A вправо по N цифры. Это эквивалентно делению A по .
Эти операции иногда записываются 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, а не 0s.
n = 0b11111101s8; bitshift(n,-2)
ans = int8
-1
Вы можете использовать bitset для изменения битов в номере. Например, измените первый бит числа 8 на 1 (что добавляет 1 к числу):
bitset(8,1)
ans = 9
По умолчанию bitset переворачивает биты на или 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
bitand | bitcmp | bitget | bitor | bitset | bitshift | bitxor