Bit-Wise Operations

This topic shows how to use bit-wise operations in MATLAB® to manipulate the bits of numbers. Operating on bits is directly supported by most modern CPUs. In many cases, manipulating the bits of a number in this way is quicker than performing arithmetic operations like division or multiplication.

Number Representations

Any number can be represented with bits (also known as binary digits). The binary, or base 2, form of a number contains 1s and 0s to indicate which powers of 2 are present in the number. For example, the 8-bit binary form of 7 is

```00000111 ```

A collection of 8 bits is also called 1 byte. In binary representations, the bits are counted from the right to the left, so the first bit in this representation is a 1. This number represents 7 because

`${2}^{2}+{2}^{1}+{2}^{0}=7.$`

When you type numbers into MATLAB, it assumes the numbers are double precision (a 64-bit binary representation). However, you can also specify single-precision numbers (32-bit binary representation) and integers (signed or unsigned, from 8 to 64 bits). For example, the most memory efficient way to store the number 7 is with an 8-bit unsigned integer:

`a = uint8(7)`
```a = uint8 7 ```

You can even specify the binary form directly using the prefix `0b` followed by the binary digits (for more information, see Hexadecimal and Binary Values). MATLAB stores the number in an integer format with the fewest number of bits. Instead of specifying all the bits, you need to specify only the left-most 1 and all the digits to the right of it. The bits to the left of that bit are trivially zero. So the number 7 is:

`b = 0b111`
```b = uint8 7 ```

MATLAB stores negative integers using two's complement. For example, consider the 8-bit signed integer -8. To find the two's complement bit pattern for this number:

1. Start with the bit pattern of the positive version of the number, 8: `00001000`.

2. Next, flip all of the bits: `11110111`.

3. Finally, add 1 to the result: `11111000`.

The result, `11111000`, is the bit pattern for -8:

`n = 0b11111000s8`
```n = int8 -8 ```

MATLAB does not natively display the binary format of numbers. For that, you can use the `dec2bin` function, which returns a character vector of binary digits for positive integers. Again, this function returns only the digits that are not trivially zero.

`dec2bin(b)`
```ans = '111' ```

You can use `bin2dec` to switch between the two formats. For example, you can convert the binary digits `10110101` to decimal format with the commands

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

The `cast` and `typecast` functions are also useful to switch among different data types. These functions are similar, but they differ in how they treat the underlying storage of the number:

Because MATLAB does not display the digits of a binary number directly, you must pay attention to data types when you work with bit-wise operations. Some functions return binary digits as a character vector (`dec2bin`), some return the decimal number (`bitand`), and others return a vector of the bits themselves (`bitget`).

MATLAB has several functions that enable you to perform logical operations on the bits of two equal-length binary representations of numbers, known as bit masking:

• `bitand` — If both digits are 1, then the resulting digit is also a 1. Otherwise, the resulting digit is 0.

• `bitor` — If either digit is 1, then the resulting digit is also a 1. Otherwise, the resulting digit is 0.

• `bitxor` — If the digits are different, then the resulting digit is a 1. Otherwise, the resulting digit is 0.

In addition to these functions, the bit-wise complement is available with `bitcmp`, but this is a unary operation that flips the bits in only one number at a time.

One use of bit masking is to query the status of a particular bit. For example, if you use a bit-wise AND operation with the binary number `00001000`, you can query the status of the fourth bit. You can then shift that bit to the first position so that MATLAB returns a 0 or 1 (the next section describes bit shifting in more detail).

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

Bit-wise operations can have surprising applications. For example, consider the 8-bit binary representation of the number $\mathit{n}=8$:

```00001000 ```

8 is a power of 2, so its binary representation contains a single 1. Now consider the number $\left(\mathit{n}-1\right)=7$:

```00000111 ```

By subtracting 1, all of the bits starting at the right-most 1 are flipped. As a result, when $\mathit{n}$ is a power of 2, corresponding digits of $\mathit{n}$ and $\left(\mathit{n}-1\right)$ are always different, and the bit-wise AND returns zero.

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

However, when $\mathit{n}$ is not a power of 2, then the right-most 1 is for the ${2}^{0}$ bit, so $\mathit{n}$ and $\left(\mathit{n}-1\right)$ have all the same bits except for the ${2}^{0}$ bit. For this case, the bit-wise AND returns a nonzero number.

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

This operation suggests a simple function that operates on the bits of a given input number to check whether the number is a power of 2:

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

The use of the short-circuit AND operator `&&` checks to make sure that `n` is not zero. If it is, then the function does not need to calculate `bitand(n,n-1)` to know that the correct answer is `false`.

Shifting Bits

Because bit-wise logical operations compare corresponding bits in two numbers, it is useful to be able to move the bits around to change which bits are compared. You can use `bitshift` to perform this operation:

• `bitshift(A,N)` shifts the bits of `A` to the left by `N` digits. This is equivalent to multiplying `A` by ${2}^{\mathit{N}}$.

• `bitshift(A,-N)` shifts the bits of `A` to the right by `N` digits. This is equivalent to dividing `A` by ${2}^{\mathit{N}}$.

These operations are sometimes written `A<<N` (left shift) and `A>>N` (right shift), but MATLAB does not use `<<` and `>>` operators for this purpose.

When the bits of a number are shifted, some bits fall off the end of the number, and `0`s or `1`s are introduced to fill in the newly created space. When you shift bits to the left, the bits are filled in on the right; when you shift bits to the right, the bits are filled in on the left.

For example, if you shift the bits of the number 8 (binary: `1000`) to the right by one digit, you get 4 (binary: `100`).

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

Similarly, if you shift the number 15 (binary: `1111`) to the left by two digits, you get 60 (binary: `111100`).

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

When you shift the bits of a negative number, `bitshift` preserves the signed bit. For example, if you shift the signed integer -3 (binary: `11111101`) to the right by 2 digits, you get -1 (binary: `11111111`). In these cases, `bitshift` fills in on the left with `1`s rather than `0`s.

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

Writing Bits

You can use the `bitset` function to change the bits in a number. For example, change the first bit of the number 8 to a 1 (which adds 1 to the number):

`bitset(8,1)`
```ans = 9 ```

By default, `bitset` flips bits to on or 1. You can optionally use the third input argument to specify the bit value.

`bitset` does not change multiple bits at once, so you need to use a `for` loop to change multiple bits. Therefore, the bits you change can be either consecutive or nonconsecutive. For example, change the first two bits of the binary number `1000`:

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

Another common use of `bitset` is to convert a vector of binary digits into decimal format. For example, use a loop to set the individual bits of the integer `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' ```

Another use of bit shifting is to isolate consecutive sections of bits. For example, read the last four bits in the 16-bit number `0110000010100000`. Recall that the last four bits are on the left of the binary representation.

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

To isolate consecutive bits in the middle of the number, you can combine the use of bit shifting with logical masking. For example, to extract the 13th and 14th bits, you can shift the bits to the right by 12 and then mask the resulting four bits with `0011`. Because the inputs to `bitand` must be the same integer data type, you can specify `0011` as an unsigned 16-bit integer with `0b11u16`. Without the `-u16` suffix, MATLAB stores the number as an unsigned 8-bit integer.

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

Another way to read consecutive bits is with `bitget`, which reads specified bits from a number. You can use colon notation to specify several consecutive bits to read. For example, read the last 8 bits of `n`.

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

You can also use `bitget` to read bits from a number when the bits are not next to each other. For example, read the 5th, 8th, and 14th bits from `n`.

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