12

I would like first to convert a number to binary, then invert it bitwise. Like this:

Number is 793 = 1100011001 then convert the binary value into: 0011100110

In JavaScript I can do the following:

var x = 793;
document.write(x.toString(2)); // gives 0011100110

This will give me the binary value of the number. But how do I invert the binary bitwise?

I tried the ~ operator, but not working probably. The output is: -1100011010

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
testjavascript
  • 121
  • 1
  • 1
  • 3
  • 1
    i guess with `793 ^ -1` you would get the bitwise inverted value of any number, just use the operator `^` with left operand as `-1` – Victor Apr 15 '19 at 15:29

6 Answers6

12

MooGoo's answer is correct.

Here is some information about what is happening.... Lets assume this is a 64 bit integer.

793 = 1100011001
~793 = -794 = 1111111111111111111111111111111111111111111111111111110011100110
0x3ff = 1111111111
(-793 & 0x3ff) = 11100110

So you could do this to solve for all cases with this code:

var x = 793; // input value
var y = x.toString(2);
var yl = y.length;
var mask = (Math.pow(2,yl)-1); // calculate mask
var result = ~x & mask;
document.write(result.toString(2)+"<br/>");
Mark At Ramp51
  • 5,343
  • 1
  • 25
  • 30
  • 1
    it wouldn't matter, if i remember correctly everything in javascript is 64bit under the covers. the result wether it's 32bit or 64bit will be the same value regardless. I just used 64 bit so i could demonstrate what the negative value really was in binary. Since the "-" doesn't exist in binary, but javascript is trying to be nice when it shows the negative sign on the number. Does that make sense? I'm not that great at explaining it. The difference with the solution i've posted is it's all mathematical. The y and yl piece can be simplified also, i just didn't have the time to get into it – Mark At Ramp51 Dec 02 '10 at 19:10
11

You need to use a bitmask.

(~793 & 0x3ff).toString(2) //11100110

Or with XOR

793 ^ 0x3ff
MooGoo
  • 46,796
  • 4
  • 39
  • 32
5

You want to XOR the binary value with 111111111 - however many 1s as there are digits in the original. So:

var x = 793;
var result = x ^ parseInt((new Array(x.toString(2).length+1)).join("1"),2);

(Code for str_repeat taken from PHP.JS)

Revisiting years later, try:

var x = 793;
var result = parseInt(x.toString(2).replace(/[01]/g,function(n) {return 1-n;}),2);

I believe this will be more efficient... probably. Could be completely wrong. Oh well.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • You can also register this is a prototype function, if you're going to use it a lot: `Number.prototype.negate = function() {return this ^ parseInt((new Array(this.toString(2).length+1)).join("1"),2);};` - This way you can have `var x = 793; var c = x.negate();` – Niet the Dark Absol Dec 02 '10 at 18:33
  • 2
    Good God, all this string munging is not very much in the spirit of bitwise operations is it? You could also do it like `793..toString(2).replace(/1/g, 'a').replace(/0/g, '1').replace(/a/g, '0')` but you'd probably cause a 6502 CPU somewhere to melt. – MooGoo Dec 02 '10 at 18:42
2

Not the shortest code but more readable. My technique is similar to @Ivo Wetzel:

const bitwiseComplement = (N) => {
  let binary = N.toString(2); // 793 is "1100011001" in binary
  binary = binary.split('').map(x => {
    return (x == 1) ? 0 : 1;
  }).join('');
  return binary; // with complement "0011100110" in binary
};

console.log(bitwiseComplement(793));

One-liner javascript solution. Regex /[0-1]/g means match a single character present in the list below [0-1].

const bitwiseComplement = (N) => {
  return N.toString(2).replace(/[0-1]/g, (v) => (v == 1 ? 0 : 1));
};

console.log(bitwiseComplement(793));
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
0

I just do this

Let's say x = -11.3 and it's a 16 bit integer from somewhere.

My results will go into variable r.

var r = ((x & 0x7FFF) ^ 0x7FFF)+1;

It's the kiss principle.

Dharman
  • 30,962
  • 25
  • 85
  • 135
-1

Update

It's unclear to me whether you want a string of the inverted value, if so you can do this:

function invert(x){
    var e = x.toString(2).split('');
    for(var i = 0, l = e.length; i < l; i++) {
        e[i] = e[i] === '0' ? '1' : (e[i] === '1' ? '0' : e[i]);
    }
    return e.join('');
}
invert(793); // '0011100110'
invert(-793); // '-0011100110'

This will also preserve leading zeros.

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112