0

Well I'm confused this isn't easier than I thought... I want to convert a twos complement binary string to the appropriate number:

-5 = '11111011' according to Wikipedia

So I would think the following would return negative 5, but it doesn't. After reading Wikipedia it seems all I have to do is subtract one then invert the bits:

~(parseInt('11111011', 2) - 1)

But it returns -251. Confusing...

Please note that I will be dealing with many odd bit lengths and all won't be 8 bits.

wayofthefuture
  • 8,339
  • 7
  • 36
  • 53

3 Answers3

1

This will take an unknown bit pattern <= 32 bits and if it is < 8 bits convert to positive int and if >= 8 with a leading 1, a negative signed int.

The trick is to pad to 32 before parseInt

const getSigned = binStr => parseInt(binStr.length >= 8 && binStr[0] === "1" ?
  binStr.padStart(32, "1") : binStr.padStart(32, "0"), 2) >> 0;

const signed = [
  "11111011",     // -5
  "01111011",     // 123
  "1111111111000" // -8
].map(getSigned);

console.log(signed);
mplungjan
  • 169,008
  • 28
  • 173
  • 236
1

After some time working on it I created this solution... if you are experienced with binary and bitwise operations please let me know your thoughts:

function getSignedInteger(bits) {
    let negative = (bits[0] === '1');
    if (negative) {
        let inverse = '';
        for (let i = 0; i < bits.length; i++) {
            inverse += (bits[i] === '0' ? '1' : '0');
        }
        return (parseInt(inverse, 2) + 1) * -1;
    } else {
        return parseInt(bits, 2);
    }
}

getSignedInteger('11111011') returns -5

wayofthefuture
  • 8,339
  • 7
  • 36
  • 53
0

I feel your confusion. The wikipedia article is showing you examples with 8 bit numbers, but you aren't generally dealing with 8 bit numbers in javascript. If you want want to explore binary number math in javascript you will probably be using 32 bits and forcing conversation to 32bit ints with bitwise operators.

So translating the wikipedia article would give you this:

-5 would look more like 11111111111111111111111111111011

All those extra zeros get flipped. With that in mind this makes a bit more sense:

let str = "11111111111111111111111111111011"
console.log(str.length, 'bits')
console.log((parseInt(str, 2) >> 0))

It should make more sense now that:

let five = '00000000000000000000000000000101'
let neg6 = '11111111111111111111111111111010'

console.log('5: ', parseInt(five, 2) >> 0)
console.log('-6: ', parseInt(neg6, 2) >> 0)

// two complement
let neg6Plus1 = '11111111111111111111111111111011'

console.log('-5: ', parseInt(neg6Plus1, 2) >> 0)
Mark
  • 90,562
  • 7
  • 108
  • 148