9

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 signed.

How do I invert an unsigned arbitrary-bit binary number?

I would like to create a function that takes in this unsigned arbitrary-bit binary number and return its inverted form( 101->010)

I want to convert from string 101 to 010

15
  • 010 -> 101 ... how would you determine that you should only flip 3 bits? why not 5 bits like in 10100 -> 01011? Commented Feb 25, 2017 at 0:36
  • I can't use ~5u because I want to pass in a number say 101 and use this function to return 010 Commented Feb 25, 2017 at 0:36
  • you are passing in strings? like '010', that can work Commented Feb 25, 2017 at 0:38
  • 1
    yes, but I'm asking how do you determine the number of bits to flip ... 010 == 0000000010 ... but 101 !== 1111111101 Commented Feb 25, 2017 at 0:41
  • 1
    @JaromandaX after the flip, 010 should be 101; that is to say it should cut off any bits left of 101 Commented Feb 25, 2017 at 0:44

8 Answers 8

11

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 2
    console.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)

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

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

The above in ES5

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

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

Sign up to request clarification or add additional context in comments.

6 Comments

Does that work for binary? Like I would be passing in a binary not decimal. It means 101 to 010( but not 10)
Does that work for binary? a String of 1's and 0's is not binary per se. All Numbers in javascript are binary, you can display them in binary, octal, decimal, hexadecimal, and all bases you can imagine ... but if you are working with strings of 1's and 0's (in a javascript String) then the second bit of code is what you want
When I put second bit of code, it gives me error. It doesn't look like a function. Should I include the first bit as well. I'm new to javacript
you're probably using internet explorer then - use the third snippet - it's ES5, which internet exploder almost understands
You don't need the parseInt in 1 - parseInt(b), the - operator will do the conversion to number. ;-)
|
8

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);     // -6
console.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:

function invert(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)

7 Comments

this would work with "arbitrary-bit binary" up to 32 (or 31?) bits only ... arbitrary suggests any number of bits :p
using significant bits ... 010 -> 01, not 101 - the issue is that the question is too vague on how to determine the number of bits are significant
5 = 101; so it's the 3 "significant" bits we're inverting (and we keep the rest at 0 as if they're not relevant to the original number).
He's not going from 2->5, only from 5->2.
010 would be inverted to 101 - it's in the question
|
0

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

1 Comment

But 5 is 101 -> 010 or 2.
0

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

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

Comments

0

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:

function flipBits(n) {
  return parseInt(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 functions
function flipStringBits(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).

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

// Tests
console.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.

2 Comments

warning, OP's environment doesn't support ES2015+ :p
@JaromandaX—ok, added ed 3 compliant code. Not tested in IE 4 but I expect it to work even there. ;-)
0

You can create a mask for number's width and take xor to flip the bits.

/**
 * @param {number} num
 * @return {number}
 */
var findComplement = function(num) {
    let len = num.toString(2).length;
    let mask = Math.pow(2, len) - 1;
    return num ^ mask;
};
console.log(findComplement(5));

Comments

0

For Integer values, you can use the javaScript program to reverse the order of the bits in a given integer and as a result return new integer as described below:

function binaryReverse(value) {
  return parseInt(value.toString(2).split('').reverse().join(''), 2);
}

console.log(binaryReverse(25));
console.log(binaryReverse(19));

Output:

 19
 25

Comments

0

This takes a string of binary digits and returns the inverse. If the string has leading 0s they will also become 1s.

const inverseBin = bin => bin.replace(/0|1/g, bit => +!+bit);

1 Comment

Notice that bit is a string so you better do === "0". Btw you don't need to put capturing groups around the digits, /0|1/g would suffice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.