Tutorial :Where would I use a bitwise operator in JavaScript?



Question:

I've read 'what are bitwise operators?', so I know what bitwise operators are but I'm still not clear on how one might use them. Can anyone offer any real-world examples of where a bitwise operator would be useful in JavaScript?

Thanks.

Edit:

Just digging into the jQuery source I've found a couple of places where bitwise operators are used, for example: (only the & operator)

// Line 2756:  event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));    // Line 2101  var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;  


Solution:1

Example:

Parses hexadecimal value to get RGB color values.

var hex = 'ffaadd';  var rgb = parseInt(hex, 16); // rgb is 16755421      var red   = (rgb >> 16) & 0xFF; // returns 255  var green = (rgb >> 8) & 0xFF;  // 170  var blue  = rgb & 0xFF;     // 221    


Solution:2

I heavily use bitwise operators for numerical convertions in production scripts, because sometimes they're much faster than their Math or parseInt equivalents.

The price I have to pay is code readability. So I usualy use Math in development and bitwise in production.

You can find some performance tricks on jsperf.com.

As you can see, browsers don't optimize Math.ceil and parseInt for years, so I predict bitwise will be faster and shorter way to do things in furure as well.

Some further reading on SO...


Bonus: cheat sheet for | 0 : an easy and fast way to convert anything to integer:

( 3|0 ) === 3;             // it does not change integers  ( 3.3|0 ) === 3;           // it casts off the fractional part in fractionalal numbers  ( 3.8|0 ) === 3;           // it does not round, but exactly casts off the fractional part  ( -3.3|0 ) === -3;         // including negative fractional numbers  ( -3.8|0 ) === -3;         // which have Math.floor(-3.3) == Math.floor(-3.8) == -4  ( "3"|0 ) === 3;           // strings with numbers are typecast to integers  ( "3.8"|0 ) === 3;         // during this the fractional part is cast off too  ( "-3.8"|0 ) === -3;       // including negative fractional numbers  ( NaN|0 ) === 0;           // NaN is typecast to 0  ( Infinity|0 ) === 0;      // the typecast to 0 occurs with the Infinity  ( -Infinity|0 ) === 0;     // and with -Infinity  ( null|0 ) === 0;          // and with null,  ( (void 0)|0 ) === 0;      // and with undefined  ( []|0 ) === 0;            // and with an empty array  ( [3]|0 ) === 3;           // but an array with one number is typecast to number  ( [-3.8]|0 ) === -3;       // including the cast off of the fractional part  ( [" -3.8 "]|0 ) === -3;   // including the typecast of strings to numbers  ( [-3.8, 22]|0 ) === 0     // but an Array with several numbers is typecast to 0  ( {}|0 ) === 0;                // an empty object is typecast to 0  ( {'2':'3'}|0 ) === 0;         // or a not empty object  ( (function(){})|0 ) === 0;    // an empty function is typecast to 0 too  ( (function(){ return 3;})|0 ) === 0;  

and some magic for me:

3 | '0px' === 3;  


Solution:3

In JavaScript, you can use a double bitwise negation (~~n) as a replacement for Math.floor(n) (if n is a positive number) or parseInt(n, 10) (even if n is negative). n|n and n&n always yield the same results as ~~n.

var n = Math.PI;  n; // 3.141592653589793  Math.floor(n); // 3  parseInt(n, 10); // 3  ~~n; // 3  n|n; // 3  n&n; // 3    // ~~n works as a replacement for parseInt() with negative numbers…  ~~(-n); // -3  (-n)|(-n); // -3  (-n)&(-n); // -3  parseInt(-n, 10); // -3  // …although it doesn’t replace Math.floor() for negative numbers  Math.floor(-n); // -4  

A single bitwise negation (~) calculates -(parseInt(n, 10) + 1), so two bitwise negations will return -(-(parseInt(n, 10) + 1) + 1).

It should be noted that of these three alternatives, n|n appears to be the fastest.

Update: More accurate benchmarks here: http://jsperf.com/rounding-numbers-down

(As posted on Strangest language feature)


Solution:4

A real life example :

^ bitwise XOR as a I/O toggler

Used like value ^= 1 will change on every call the value to 0, 1, 0, 1 ...

function toggle(evt) {    evt.target.IO ^= 1;                                    // Bitwise XOR as 1/0 toggler    evt.target.textContent = evt.target.IO ? "ON" : "OFF"; // Unleash your ideas  }    [...document.querySelectorAll("button")].forEach( el =>    el.addEventListener("click", toggle)  );
<button>OFF</button>  <button>OFF</button>  <button>OFF</button>


Solution:5

Given the advances Javascript is making (especially with nodejs that allows server side programming with js), there is more and more complex code in JS. Here are a couple of instances where I have used bitwise operators:

  • IP address operations:

    //computes the broadcast address based on the mask and a host address  broadcast = (ip & mask) | (mask ^ 0xFFFFFFFF)      //converts a number to an ip adress   sprintf(ip, "%i.%i.%i.%i", ((ip_int >> 24) & 0x000000FF),                           ((ip_int >> 16) & 0x000000FF),                           ((ip_int >>  8) & 0x000000FF),                           ( ip_int        & 0x000000FF));  

Note: this is C code, but JS is almost identical

  • CRC algorithms uses them a lot

Check out the wikipedia entry on this

  • Screen resolution operations


Solution:6

To tell if a number is odd:

function isOdd(number) {      return !!(number & 1);  }    isOdd(1); // true, 1 is odd  isOdd(2); // false, 2 is not odd  isOdd(357); // true, 357 is odd  

Faster than modulus - use where performance really counts!


Solution:7

Few other examples of how to use bitwise not and double bitwise not:

Floor operation

~~2.5    // 2  ~~2.1    // 2  ~~(-2.5) // -2  

Check whether indexOf returned -1 or not

var foo = 'abc';  !~foo.indexOf('bar'); // true  


Solution:8

You can use them for flipping a boolean value:

var foo = 1;  var bar = 0;  alert(foo ^= 1);  alert(bar ^= 1);  

This is a bit silly though and for the most part bitwise operators do not have many applications in Javascript.


Solution:9

Bitmasks.

Used extensively, for example, in JS events.


Solution:10

var arr = ['abc', 'xyz']  

Annoyed to write

if (arr.indexOf('abc') > -1) {    // 'abc' is in arr  }    if (arr.indexOf('def') === -1) {    // 'def' is not in arr  }  

to check if something is inside an array?

You can use the bitwise operator ~ like so:

if (~arr.indexOf('abc')) {    // 'abc' is in arr  }    if (! ~arr.indexOf('def')) {    // 'def' is not in arr  }  


Solution:11

I've used it once for a permissions widget. File permissions in unix are a bitmask, so to parse it, you need to use bit operations.


Solution:12

I'm using them to flatten three numbers into 1 as a way of storing multidimensional arrays in a Uint16Array. Here is a snippet of a voxel game I'm developing:

function Chunk() {    this._blocks = new Uint16Array(32768);    this._networkUpdates = [];  }    Chunk.prototype.getBlock = function(x, y, z) {    return this._blocks[y + (x << 5) + (z << 10)];  };    Chunk.prototype.setBlock = function(x, y, z, value) {    this._blocks[y + (x << 5) + (z << 10)] = value;    this._networkUpdates.push(value + (y << 15) + (x << 20) + (z << 25));  };    Chunk.prototype.getUpdates = function() {    return this._networkUpdates;  };    Chunk.prototype.processUpdate = function(update) {    // this._blocks[Math.floor(update / 65536)] = update % 65536;    this._blocks[update >> 16] = update & 65535;  };    var chunk = new Chunk();  chunk.setBlock(10, 5, 4);  alert(chunk.getBlock(10, 5, 4));  alert(chunk.getUpdates()[0]);


Solution:13

They seem to be very useful when you work with hex values and bits. Since 4 bits can represent 0 to F.

1111 = F 1111 1111 = FF.


Solution:14

Example using Node.js

Presuming you had a file (called multiply.js) with these contents, you could run

`node multiply <number> <number>`  

and get an output consistent with using the multiplication operator on the same two numbers. The bit shifting going on in the Mulitply function is an example of how to take the bit mask representing one number and use it to flip bits in another number for fast operations.

var a, b, input = process.argv.slice(2);    var printUsage = function() {    console.log('USAGE:');    console.log('  node multiply <number> <number>');  }    if(input[0] === '--help') {+    printUsage();    process.exit(0);  }    if(input.length !== 2) {    printUsage();    process.exit(9);  }    if(isNaN(+input[0]) || isNaN(+input[1])) {    printUsage();    process.exit(9);  }    // Okay, safe to proceed    a = parseInt(input[0]),  b = parseInt(input[1]);    var Multiply = function(a,b) {    var x = a, y = b, z = 0;      while( x > 0 ) {      if(x % 2 === 1) {        z = z + y;      }      y = y << 1;      x = x >> 1;    }      return z;  }    var result = Multiply(a,b);    console.log(result);  


Solution:15

This answer contains explanations of Mark's answer.

By reading these explanations and running the code snippet an idea can be gained.

var hex = 'ffaadd';  var rgb = parseInt(hex, 16); // rgb value is 16755421 in decimal = 111111111010101011011101 in binary = total 24 bits      var red   = (rgb >> 16) & 0xFF; // returns 255  var green = (rgb >> 8) & 0xFF;  // returns 170  var blue  = rgb & 0xFF;         // returns 221      // HOW IS IT    // There are two bitwise operation as named SHIFTING and AND operations.  // SHIFTING is an operation the bits are shifted toward given direction by adding 0 (zero) bit for vacated bit fields.  // AND is an operation which is the same with multiplying in Math. For instance, if 9th bit of the given first bit-set is 0  // and 9th bit of the given second bit-set is 1, the new value will be 0 because of 0 x 1 = 0 in math.    // 0xFF (000000000000000011111111 in binary) - used for to evaluate only last 8 bits of a given another bit-set by performing bitwise AND (&) operation.   // The count of bits is 24 and the first 16 bits of 0xFF value consist of zero (0) value. Rest of bit-set consists of one (1) value.  console.log("0xFF \t\t\t\t: ", 0xFF)       // 111111111010101011011101 -> bits of rgb variable  // 000000000000000011111111 -> 255 after (rgb >> 16) shifting operation  // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)  // 000000000000000011111111 -> result bits after performing bitwise & operation  console.log("Red - (rgb >> 16) & 0xFF \t: ", (rgb >> 16) & 0xFF) // used for to evaluate the first 8 bits    // 111111111010101011011101 -> bits of rgb variable  // 000000001111111110101010 -> 65450 -> 'ffaa'  // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)  // 000000000000000010101010 -> result bits after performing bitwise & operation  // calculation -> 000000001111111110101010 & 000000000000000011111111 = 000000000000000010101010 = 170 in decimal = 'aa' in hex-decimal  console.log("Green - (rgb >> 8) & 0xFF \t: ", (rgb >> 8) & 0xFF) // used for to evaluate the middle 8 bits     // 111111111010101011011101 -> 'ffaadd'  // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)  // 000000000000000011011101 -> result bits after performing bitwise & operation   // calculation -> 111111111010101011011101 & 000000000000000011111111 = 221 in decimal = 'dd' in hex-decimal  console.log("Blue - rgb & 0xFF \t\t: ", rgb & 0xFF) // // used for to evaluate the last 8 bits.    console.log("It means that `FFAADD` hex-decimal value specifies the same color with rgb(255, 170, 221)")    /* console.log(red)  console.log(green)  console.log(blue) */


Solution:16

I just found this question trying to confirm if the bitwise AND operator also was & in Javascript.

Since you asked for an example:

if ($('input[id="user[privileges]"]').length > 0) {      $('#privileges button').each(function () {          if (parseInt($('input[id="user[privileges]"]').val()) & parseInt($(this).attr('value'))) {              $(this).button('toggle');          }      });  }  

It populates the state of buttons with jQuery given a bitmask value of a hidden field:

  • none = 0
  • user = 1
  • administrator = 2
  • user + administrator = 3

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »