I’m sure you’ve heard of binary numbers. They are extremely important for the operation of a computer. But do you know how they work? And why exactly does the computer use this system?

In this reading lab, we learn everything about bits and bytes. What we learn here we can of course also apply in real life! This is why we have prepared a follow-up project for you:

‘Bits en bytes met een ledmatrix’. So you can it, once you’re done reading!

  • Note: In this article, for binary numbers, we use the common prefix ‘0b’ to avoid confusion (1 becomes 0b1).

How does the binary system work?

Binary numbers are quite similar to the system we use on a daily basis, but there is one big difference. The decimal number system contains ten digits, which you know, these are 0, 1, 2, 3, and so on. The binary system, on the other hand, has only two, 0 and 1.

However, this does not mean that in the binary system we can only count til 1. Just like in the decimal system we can combine the single digits to make larger numbers. For example, 10 is a composition of 1 and 0, it stands for the number that comes after 9 (9+1=10). This works exactly the same in the binary system, after 0b1 comes for example 0b10 (0b1+0b1=0b10), so the number 0b10 is the next number after 0b1.

So, by adding more digits each time, we can count infinitely far in the binary system as well. For example, with four characters, we get to 15:

0 0b0000
1 0b0001
2 0b0010
3 0b0011
4 0b0100
5 0b0101
6 0b0110
7 0b0111
8 0b1000
9 0b1001
10 0b1010
11 0b1011
12 0b1100
13 0b1101
14 0b1110
15 0b1111

However, we see something strange in this table, the numbers each consist of four digits, with some numbers zeros, are added on the left side. We never do this when we work with decimal numbers because 005 does not state. But in the binary system this can be very useful. This has to do with the operations a computer perform:

Bits

Computers use bits, a bit is as it were a place for a binary digit, and can, therefore, contain a 1 or a 0. So we will have to reserve a bit for each binary digit we want to use, the number of bits is fixed. For example, if we reserve 8 bits, we can store a number between 0 and 255, so this number can never exceed 255.

Bytes and data types

A computer group bits into groups of eight. Such a group is called a byte. Grouping improves the efficiency of the computer. The computer no longer needs to keep track of where each bit is, the computer does this byte by byte.

Because of this grouping, a programmer will almost always choose to reserve a multiple of eight bits for a number. This is also done for you by the programming language. We use data types for this. By specifying which data type you want to use, you can determine exactly how many bytes the computer will need to reserve. For example, a byte or a char contains only one byte, a short has two, an int generally consists of four bytes and a long is the largest, it usually has eight bytes.

However, a data type indicates more than just how many bytes the computer needs to reserve. It also indicates how the data should be stored and interpreted. An ordinary short, int, and long, for example, uses the first bit to indicate whether the number is positive or negative, so this bit does not belong to the number. However, as a programmer, we can often influence these things. For example, we can make these short, int, or long ‘unsigned’ to prevent this, but then we will not be able to use negative numbers.

In C++, the length of the different data types can vary from time to time. When this can cause problems you can also use the data types int64_t and uint64_t. The number (in this case 64) indicates how many bits should be reserved (you can choose between 8, 16, 32 and 64), the ‘u’ stands for unsigned. For AVR boards like the Arduino, bytes, and shorts are the default length, but an int is just like a short 2 bytes long, and a long is 4 bytes long.

Why binary numbers?

You may be wondering: Why do computers use the binary system? This is because of the most important component of the computer: the transistor, and its predecessor: the vacuum tube. A transistor can only be in two states: open or closed. The current wire, which is connected to the transistor, may or may not run voltage. These states correspond well with the 1 and the 0 of the binary system.

And the transistor has been chosen because it makes different operations, such as adding numbers, easy.

Bitwise operators

Besides addition, many other operations are possible, some are much simpler, these are the bitwise operators. And precisely because of their simplicity, these are also the most important operations a computer can make. Every bitwise operator is used in almost every program.

NOT (~)

The NOT operation is the very simplest binary operation that exists. You enter one number, and one number comes out. The result is exactly the opposite of what you give as input:


To indicate a NOT operation we use, in computer code, the ~-sign. So the result of ~0b10100110 is 0b01011001. As you can see, the operation is performed separately for each position.

AND (&)

To perform an AND operation, we need two numbers. Only when both numbers are one will the answer be one. Otherwise the answer will be zero:

For an AND operation, the & symbol is used. The operation 0b010101 & 0b00001111 will thus give the number 0b00000101.

The AND operation can also be viewed from another point of view. When we speak of ‘bitmasking’ we see the second number we enter as a kind of mask. In the mask we fill in a one at the positions of which we want to keep the value. At the positions of which we want to discard the value, we enter a zero in the mask. At the positions of the discarded numbers, there will always be a zero in the answer (just look at the table above).

So for example, if we enter 0b010101 with the mask 0b00001111, we see that the first four digits are masked. So the result of this operation will be 0b00000101 (0b010101 & 0b00001111). The masked digits have been changed to zero, while the unmasked digits have been unmasked.

OR ( | )

The OR operation is very similar to the AND operation. However, the difference is that only one of the two entered numbers needs to be one to get one as a result:

We use the | sign for OR processing. This means that the operation 0b010101 | 0b00001111 will result in the number 0b01011111.

Like the AND operation, we can also use the OR operation to bitmask. However, we use a one in the mask to indicate that a digit should be masked. In the end result, the digit at this position will always be a one. So for example, if we enter the number 0b010101 and use the mask 0b11110000 the result will be 0b11110101. So we see that the masked digits change to one, the other numbers remain unchanged.

XOR (^)

XOR means OR, but not AND. When the bits differ from each other, the result will be one, otherwise zero will come out. This is clearly shown in the following table:

0b010101 ^ 0b00001111 will be 0b01011010.

We can also see the XOR operation from the point of view of bitmasking. The positions where we will enter a one in the ‘mask’ will be reversed (just like a NOT operation). 0b010101 with the ‘mask’ 0b00001111 will get the number 0b01011010 as a result. However, technically this process is not called bit masking, because the digits of the entered number will affect the position of the mask.

Bitshift(<<, >>)

Bit shifting is quite different from the above-mentioned operations. The end result of one single bit, unlike the other operations, depends on its neighbors. When we bitshift, we move all bits to the left or right. Bits that fall off the edge will be forgotten, bits that are added will be a zero. Below we see this process in operation:

We see that the sign ‘<<‘ moves all bits to the left. ‘>>’ moves all bits to the right.

Complex operations

By merging the simple operations mentioned above in convenient ways, computers can also perform more complex operations. In this way, we can, for example, perform common mathematical operations such as addition, subtraction, multiplication, and division.

Computers do this, for the common operations, however, not by performing the simple operations one after the other. These complex operations are done in hardware. Because of this, they will be performed much faster than what could be done by the bitwise operators.

In real life

What we have learned here we can of course also apply in real life! We have prepared a follow-up project for you:  ‘Bits en bytes met een ledmatrix’.