Bitwise Operations, the basics

Introduction


Many developers don't bother with bitwise operators, mostly because people don't know them well enough. There is also the argument of where they fit in everyday programming, like web development. There is a high likelihood people will confuse a & b for a && b, the first will treat operands as bits (32 bits to be precise) and the second is your everyday Boolean operation. A quick refresher on truth tables is in order here, to fully understand bitwise operators. For the sake of simplicity and brevity, let's focus on the most important 2, AND and OR (click here to learn more).

AND

Assuming we have two operands each having a single bit (1 or 0), this operator will return 1 if and only if both operands are 1s. Common operators used to denote the AND operation are , K, & and .

To put it in simpler terms, if A and B are both 1 then the result is 1, if either operand is not 1 the result is 0.

OR

Using the same variable as the AND example, the OR operator will return 1 either on or the other operand is 1.

How is this truth table thing useful to you?


First things first, those operators also work on operands with more tha one bit, for example, 1010 & 1000 = 1000 or 1010 | 1000 = 1010. Note that this operation is not performed as a sequence of bits (0s and 1s) and not decimal or some other number notation. Now, let's assume JavaScript is your programming language of choice (this works for other languages, check docs). It is quite easy to perform bitwise operations on numbers and use this as a way of making your code more efficient and easier to work with.

const variable = 8;
variable.toString(2); // result is 1000

If we wanted to build a simple ACL. Typically, you would create a list of permissions (for example, Create, Read, Update and Delete) and create a role that you could assign to a user.

// permissions
const permissions = {
    create: CREATE,
    read: READ,
    update: UPDATE,
    remove: DELETE. // delete is keyword in JavaScript
}

const AdminRole = ['CREATE', 'READ', 'UPDATE', 'DELETE'];
const Admin = {
    name: "Super Admin",
    role: AdminRole,
    // other fields
}

function createAndReadPost(post, role) {
    if (!role.includes('CREATE')) {
        throw new Error("Not authorized");
    }
    // create post
    if (!role.includes('READ')) {
        throw new Error("Not authorized");
    }
    // read post
}
createAndReadPost(postObject, admin.role);

This will work, but can get complicated quickly especially if we need to combine permission this way. Let's not get started on how much storage this will consume if you were building something like a CMS. Enter bit field flags. It is possible to represent these permissions using bits.

const CREATE = 1; // 0001
const READ = 2; // 0010
const UPDATE = 4; // 0100
const DELETE = 8; // 1000

const AdminRole = CREATE | READ | UPDATE | DELETE; // 1111
const Admin = {
  name: 'Super Admin',
  permissions: AdminRole,
};

function createAndReadPost(post, role) {
  if (CREATE & (role === 0)) {
    throw new Error('Not authorized');
  }
  // create post
  if (READ & (role === 0)) {
    throw new Error('Not authorized');
  }
  // read post
}
createAndReadPost(postObject, admin.permissions);

Quick comparison, "READ" is 4 bytes and in the bitwise example AdminRole, with all four permissions is 32 bits. There is the case of bitwise operations also being multiple times more efficient that string comparison.

Conclusion


There are many other use cases for bitwise operations, they can be very powerful tools to add efficiency and improved readability to your programs. Not to mention there are many other bitwise operators not covered in this post.

No Comments Yet