Bit-masking, Bitwise operation: What is it, and how do I use it daily?

Originally posted: LinkedIn

Hello mate, in this short article I want to share about bit-masking and bitwise operation based on my own experience. Some of you might know this technique very well and have more experience than me, but I hope you guys enjoy this article.

What is Bitwise operation?

Statically typed programming languages like Go and C# generally do not allow running logical operations directly over number types like unsigned or signed integers. However, JavaScript treats numbers using logical operators similarly to how bitwise operations work.

Bitwise operators

  • AND (&)
  • OR (|)
  • NOT (~)
  • XOR (^)
  • SHIFT Left/Right (<<, >>)

A shift operation moves the bits by a given number of positions. For example, 3 << 1: 3 is 0b00000011 in binary. Shifting it to the left by 1 position results in 6 or 0b00000110.

This operation can efficiently replace procedures involving arrays of Booleans, which would otherwise allocate more memory than a single integer variable.

What is Bit-masking and how does it correlate with Bitwise operation?

Bit-masking is the process of using bitwise operations to achieve or check a conditional state utilizing binary representation.

Suppose we have an array of Booleans [false, false, true] and we want to check the value at index 1. In a standard implementation, we would access the array at index 1 and get false.

Now, let's represent this array using binary: 0b00000100 (which is 4 as an 8-bit unsigned integer). How do we access the condition of index 1 in this representation?

The Procedure:

  1. Define the index in binary representation.
  2. Start with an initial condition (e.g., 1 or 0b00000001).
  3. Shift that value left by the index number.
  4. Perform an AND operation between the representation and the shifted value.
  5. If the result is greater than 0, it means true; otherwise, it's false.

Example:

  • Bit position for index 1: 1 << 1 = 2 (0b00000010)
  • Calculate: 0b00000100 & 0b00000010 = 0b00000000 (Result: 0, which means false)
  • For index 2: 1 << 2 = 4 (0b00000100)
  • Calculate: 0b00000100 & 0b00000100 = 0b00000100 (Result: 4, which means true)

My Experience with Bit-masking

In my experience, this technique is particularly useful for multiple adapter initiation and unit test assertions. While unit tests don't always require extreme optimization, I use bit-masking in several cases to keep myself motivated and avoid the monotony of standard CRUD tasks.

Multiple Adapter Initiation

Imagine having multiple connection strings to different databases. We define the index of each connection string in the configuration or source code. We can then use an "activation schema" — a binary representation of which databases are active.

A function evaluates the activation schema with bit-masking:

  • If the activation schema is 0b00000101 (5) and we have 4 databases, the function might return: ["connection-string-A", "", "connection-string-C", ""].
  • If the schema is 0b00000001, it returns: ["connection-string-A", "", "", ""].

These processed connection strings are then passed to a database initiation function to create the necessary adapters.

Closing

That’s all! I’m happy to share this article, and more importantly, it serves as a helpful note for myself.

Thank you, adios!