0

I have the following string in JavaScript: "1011100111100110101110110".

I want to perform an operation on it, that will return its complement (aka, all the ones replaced by zeros and all the zeroes replaced by ones).

The javascript documentation says the NOT operator will do exactly that, but in my tests, it does not give me what I expect.

I guess my types are wrong to start off with.

This is my test code:

var nMyNumber = "1011100111100110101110110";
var sBinString = nMyNumber.toString(2);
console.log("Number: " + sBinString);

var reverse = ~sBinString;
console.log("Complement: " +  reverse);
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
Harriet
  • 1,633
  • 5
  • 22
  • 36
  • 3
    What you have there is not "binary"; it's just a string of ones and zeros. So binary operators won't work as you think they do on actual binary values. You can't ever directly "see" the kind of binary `~` works on, only some abstract representation of it (e.g. ints). – deceze Jul 13 '17 at 08:42
  • OK - I had an idea that the types are not correct; My need is to have the complement of the nMyNumber string, and then to convert that result into decimal... – Harriet Jul 13 '17 at 08:46

6 Answers6

4

just do string replacement

var sBinString = nMyNumber
                .replace(/1/g,'x')//convert '1' to temp char('x')
                .replace(/0/g,'1')//convert '0' to '1'
                .replace(/x/g,'0')//finally convert temp char to '0'
Azad
  • 5,144
  • 4
  • 28
  • 56
3

Your casting is wrong. One solution can be using map:

var nMyNumber = "1011100111100110101110110";
var reverse = nMyNumber.split('').map(x => x === "0" ? "1" : "0").join('');    
console.log("Number: " + reverse);
OmG
  • 18,337
  • 10
  • 57
  • 90
  • I get an error when I add this line to my code: Uncaught TypeError: nMyNumber.map is not a function. Have you tried it? – Harriet Jul 13 '17 at 08:51
1

If you actually want a number, first convert your string into one:

var x_as_binary_string = "1011100111100110101110110"
var x = parseInt(x_as_binary_string, 2);

Now to get this number's complement, use NOT as you said:

var complement = ~ x;

If you need it converted back into a binary string:

var complement_as_string = complement.toString(2);
slim
  • 40,215
  • 13
  • 94
  • 127
0

Strings do not have complements. Numbers can have binary complements. If you want the string that would result from complementing the binary value that happens to be in a string, you will have to write your own function to do that. One way to do that would be to compute the value your binary string represents, complement that, and convert that new number to a binary string.

slim
  • 40,215
  • 13
  • 94
  • 127
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

The ~ Bitwise operator doesn't give you the expected output since which performs NOT operation on each bit in a signed 32bit representation and the result is converted back to the normal number so you don't get the expected result.

From MDN docs :

The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format. Two's complement format means that a number's negative counterpart (e.g. 5 vs. -5) is all the number's bits inverted


Bitwise NOTing any number x yields -(x + 1). For example, ~5 yields -6.

Even though it's not going to work as expected, there are some bugs in your code:

  1. nMyNumber.toString(2) won't do anything, which returns the same string. So you need to convert into number using parseInt with a radix of 2(for binary).
  2. Finally reverse would hold a number which logs as in a decimal format, to convert into binary use toString(2)(where 2 stands for the binary format, eg reverse.toString(2)).

Use String#replace with a callback function and within the function return character based on the matched value.

var nMyNumber = "1011100111100110101110110";

console.log(
  nMyNumber.replace(/[01]/g, function(m) {
    return m == 0 ? '1' : 0;
  })
)

// with ES6 arrow function
console.log(
  nMyNumber.replace(/[01]/g, m => m == 0 ? '1' : 0)
)
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
-1

How about a simpler approach ->

var nMyNumber = "1011100111100110101110110";
nMyNumber = nMyNumber.split("");
var myNumber = [];
for(var i=0;i<nMyNumber.length;i++) {
    if(nMyNumber[i] == 0) {
        myNumber.push(1);
    }
    if(nMyNumber[i] == 1) {
        myNumber.push(0);
    }
}
myNumber.join("");
console.log(myNumber);
Trishant Pahwa
  • 2,559
  • 2
  • 14
  • 31
  • How is this simpler? Simper to what? – Scott Hunter Jul 13 '17 at 12:43
  • Simpler to understanding sir. No doubt using a map function would be shorter, but even that function call would be performing this very operation repeatedly using an anonymous function. – Trishant Pahwa Jul 13 '17 at 16:36
  • This code does not work. The second `if` should be a `else if` (or an `else`), because if the first condition matches, the replacement is made immediately, thus matching also the second condition. In the end, you have a string with all zeroes... Also, the `Array.toString` method will concatenate the entries with a comma, while the `Array.join` function with an empty string as parameter will provide the expected result – 3rgo Apr 04 '20 at 17:00