Where would I use a bitwise operator in JavaScript?

JavascriptBitwise Operators

Javascript Problem Overview


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;

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 - Javascript

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 https://stackoverflow.com/questions/1995113/strangest-language-feature/2019171#2019171)

Solution 4 - Javascript

^ bitwise XOR as toggler

value ^= 1 will change on every call the value to 0, 1, 0, 1, ... , (it's basically similar to: boolVal != boolVal):

function toggle(evt) {
  const EL = evt.currentTarget;
  EL.isOn ^= 1; // Bitwise toggle
  EL.textContent = EL.isOn ? "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 - Javascript

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 - Javascript

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 - Javascript

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 - Javascript

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 - Javascript

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 10 - Javascript

Bitmasks.

Used extensively, for example, in JS events.

Solution 11 - Javascript

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 - Javascript

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 13 - Javascript

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 14 - Javascript

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 15 - Javascript

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 16 - Javascript

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJamesView Question on Stackoverflow
Solution 1 - JavascriptMarkView Answer on Stackoverflow
Solution 2 - JavascriptDanView Answer on Stackoverflow
Solution 3 - JavascriptMathias BynensView Answer on Stackoverflow
Solution 4 - JavascriptRoko C. BuljanView Answer on Stackoverflow
Solution 5 - JavascriptBogdan Gavril MSFTView Answer on Stackoverflow
Solution 6 - JavascriptdanwellmanView Answer on Stackoverflow
Solution 7 - JavascriptPavel PodlipenskyView Answer on Stackoverflow
Solution 8 - JavascriptAndrew HareView Answer on Stackoverflow
Solution 9 - JavascriptYann BertrandView Answer on Stackoverflow
Solution 10 - JavascriptYuval AdamView Answer on Stackoverflow
Solution 11 - JavascripttroelsknView Answer on Stackoverflow
Solution 12 - JavascriptefkanView Answer on Stackoverflow
Solution 13 - JavascriptBardi HarborowView Answer on Stackoverflow
Solution 14 - JavascripteternautaView Answer on Stackoverflow
Solution 15 - JavascriptmysterluneView Answer on Stackoverflow
Solution 16 - JavascriptAlix AxelView Answer on Stackoverflow