Reputation: 147
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
Upvotes: 9
Views: 11491
Reputation: 1
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);
Upvotes: 0
Reputation: 7129
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
Upvotes: 0
Reputation: 3810
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));
Upvotes: 0
Reputation: 147413
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.
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.
Upvotes: 0
Reputation: 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 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
Upvotes: 11
Reputation: 1
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")
)
Upvotes: 0
Reputation: 43820
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
Upvotes: 0
Reputation: 1129
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)
Upvotes: 8