loading...
markdown guide
 

Computers are really stupid. They can only count to one. One would assume that this would make them useless, but they can do this very fast and a lot of times at once.

Counting in zeroes and one is called "binary". Binary numbers don't go "1, 2, 3, 4, 5" but instead, they go "1, 10, 11, 100, 101". The single digits in these numbers are called "bits". One can do math with these bits, but some math operations are faster than others on your computer: especially those who perform operations bit by bit without relying on other bits of the number, called "bitwise operations".

There are basically two kinds of bitwise operations: shifting and masking. Bit shifting allows you to multiply (shift left) or divide (shift right) by a multiple of 2 (2, 4, 8, 16, 32...), but results only in whole numbers. Bit masking allows you to switch single bits on and off, for example, if you need to know if a number is even or odd, you can just remove every bit but the one representing the "1" by using number & 1 and if it's set, you have an odd number. Or if you want to add 1 if the number is even, you could use number | 1.

Nowadays, computer and language compilers / interpreters are so fast that one rarely needs to use binary operations. The last time I used them in JavaScript was for centering a node during a mouse movement in IE6 (width >> 1 / height >> 1).

 

IIRC you cannot assume what number primitives correspond to what bits nor that shifting corresponds to dividing and multiplying by 2. Big/little endian aside, the spec doesn't enforce it (in every language). That's one of the reasons we have boolean operators in the first place.

 

While this may not be the case in every language, at least JavaScript got you covered:

Shift operators convert their operands to 32-bit integers in big-endian order and return a result of the same type as the left operand. The right operand should be less than 32, but if not only the low five bits will be used (see developer.mozilla.org/en-US/docs/W...).

 

How often do you need to perform operations on individual bits? This is more the stuff of lower-level languages like C and C++; they do turn up in JavaScript but it's quite rare that they're needed.

One common use for bitwise operators is in defining and checking bitmasks. This frequently comes up with the concept of permissions: PostgreSQL needs to know if a user can select from a table, insert into it, update records, and so forth. Each of these is a simple boolean flag on its own, but there are several of them, and when you consider that each user may have a different permission set for each table, it's a lot to keep track of.

Bitmasks consolidate these flags into a single value by assigning each flag one bit. The first four permissions look like this:

#define ACL_INSERT      (1<<0)  /* for relations */
#define ACL_SELECT      (1<<1)
#define ACL_UPDATE      (1<<2)
#define ACL_DELETE      (1<<3)

A user-table permission set is then rolled up into a single number. Continuing with these first four, we might see a value like this:

   bit: 8 4 2 1
on/off: 1 0 1 1

A user with this permission set can insert (1<<0 = the 1 bit), select (1<<1 = the 2 bit -- shifted left by one), and delete records. Expressed as an integer, the value of this nybble (half a byte) is eleven, which is a lot easier to throw around than four independent variables.

Checking permissions is also easy with a bitmask: just perform a bitwise and (&) between the bitmask and the permission you're checking. Let's test whether the user can perform a select:

        bit: 8 4 2 1
 user value: 1 0 1 1
 perm value: 0 0 1 0
bitwise and: 0 0 1 0

Since a bit has to be 'on' in both to appear in the result, the user has access if and only if the result of the bitwise and equals the value of the permission being tested.

 

Hey, you can check my project. unsuitable001.github.io/BitViz

This is a visualization app that shows how Bitwize operators and other mathematical operations take place.

It's open source & under MIT License. git - GitHub.com/unsuitable001/BitViz

 

I will assume this particular 5 year old is pretty advanced and know computers use 1's and 0's and that a CPU is what does the computation (to avoid sounding really condescending).

CPU's work on groups of bits rather than individual ones. Those groups are called bytes. Now there are some cases in which we do want to set the values of some specific bit inside a byte, but the CPU just sees a byte, not a collection of bits! So we need operations on bytes that will allow us to control every single bit. Binary operators let us control individual bits or groups of bits smaller than a byte.

Usually people want to use bitwise operators so they need fewer bits/bytes in total and their program becomes faster or requires less memory/storage. But computers have gotten so fast now that the speed increase is often not worth the effort.


End of ELI5

I would note that this explanation is not entirely correct as bitwise operators may work on types larger than one byte, but the idea is the same.

I've seen bitwise operators used for:

  • Database key on a distributed system: some bits in a 64-bit key were used to determine which machine the entry was stored on while others were used to get the exact entry on that machine. This is no longer a good approach as there are mature NoSQL databases out there that do the same but better.
  • Unions of large boolean arrays. Boolean types are often 32-bit, so you have a potential 32 times speedup here (1 boolean or serves as 32 binary or).
  • Legacy code
  • My own C code during a High Performance Computing project (-:
Classic DEV Post from Jan 24

What was your win this week?

Got to all your meetings on time? Started a new project? Fixed a tricky bug?

Saurabh Sharma profile image
Web development | #javaScript #css #reactjs