Skip to content Skip to sidebar Skip to footer

Invert Unsigned Arbitrary Binary Bits In Javascript

For instance, 10100 would be inverted to 01011; 010 would be inverted to 101; 101 would be converted to 010. The problem is when I use ~5, it becomes -6 because js uses 32 bit sign

Solution 1:

You can create a function that flips the required number of digits like so

var flipbits = function (v, digits) {
        return ~v & (Math.pow(2, digits) - 1);
    }
    console.log(flipbits(5, 3)); // outputs 2console.log(flipbits(2, 3)); // outputs 5

note - this isn't "arbitrary number of bits" ... it's 32 at best

working with strings, you can have arbitrary bit length (this one wont work without transpiling in Internet Exploder)

varflipbits = str => str.split('').map(b => (1 - b).toString()).join('');

    console.log(flipbits('010')); // outputs 101console.log(flipbits('101')); // outputs 010

The above in ES5

var flipbits = functionflipbits(str) {
      return str.split('').map(function (b) {
        return (1 - b).toString();
      }).join('');
    };

    console.log(flipbits('010')); // outputs 101console.log(flipbits('101')); // outputs 010

Solution 2:

Inverting the bits will always be the same, but to convert an unsigned integer to a signed integer you can use the unsigned >>> shift operator to work on unsigned numbers:

console.log(~5);     // -6console.log(~5>>>0); // 4294967290

If you want to make sure you only flip the significant bits in the number, you'll instead want to mask it via an & operation with how many significant bits you need. Here is an example of the significant bit masking:

functioninvert(x) {
  let significant = 0;
  let test = x;

  while (test > 1) {
    test = test >> 1;
    significant = (significant << 1) | 1;
  }

  return (~x) & significant;
}

console.log(invert(5));  // 2 (010 in binary)

Solution 3:

In JavaScript, ~ or tilde does this

-(N+1)

So your current operation is correct but not what you are looking for:

~5
-(5 + 1)-6

Reference

Solution 4:

You can use String.prototype.replace() with RegExp/(0)|(1)/

functiontoggle(n) {
  return n.replace(/(0)|(1)/g, function(m, p1, p2) { return p2 ? 0 : 1 });
}
    
console.log(
  toggle("10100"),
  toggle("101")  
)

Solution 5:

You can use a function that converts numbers to binary as a string, flips the 0s and 1s, then converts back to a number. It seems to give the expected results, but looks pretty ugly:

functionflipBits(n) {
  returnparseInt(n.toString(2).split('').map(bit =>1 - bit).join(''),2)
}

[0,1,2,3,4,5,123,987679876,987679875].forEach(
   n =>console.log(n + ' -> ' + flipBits(n))
);

Maybe there's a mix of bitwise operators to do the same thing.

Edit

It seems you're working with strings, so just split, flip and join again:

// Requires support for ECMAScript ed 5.1 for map and // ECMAScript 2015 for arrow functionsfunctionflipStringBits(s) {
  return s.split('').map(c =>1 - c).join('');
}

['0','010','110','10011100110'].forEach(
  v =>console.log(v + ' -> ' + flipStringBits(v))
);

Basic function for ECMAScript ed 3 (works everywhere, even IE 4).

functionflipStringBitsEd3(s) {
  var b = s.split('')
  for (var i = 0, iLen = b.length; i < iLen; i++) {
    b[i] = 1 - b[i];
  }
  return b.join('');
}

// Testsconsole.log('Ed 3 version');
var data = ['0', '010', '110', '10011100110'];
for (var i = 0, iLen = data.length; i < iLen; i++) {
  console.log(data[i] + ' ->\n' + flipStringBitsEd3(data[i]) + '\n');
}

Works with any length string. The ed 3 version will work everywhere and is probably faster than functions using newer features.

Post a Comment for "Invert Unsigned Arbitrary Binary Bits In Javascript"