Robert C. Holland
Robert C. Holland

Reputation: 1813

How to convert from unsigned to 2's complement in js

I'm trying to convert binary unsigned number to two's complement with javascript:

function bin_input_to_num(input) // 2 bit, input is string
{
    return ~Number('0b' + input) + '0b01'; // using ES6
}

console.log(bin_input_to_num('11'));  // actual: -3, expected: -1

I'm not sure what I'm missing.

(edit: I have carefully read through the marked possible duplicate question and answers, and it doesn't resolve my issue here)

Upvotes: 2

Views: 2414

Answers (2)

Carl Younger
Carl Younger

Reputation: 3070

Why not just check if it's in the negative range, then adjust accordingly? Something like this:

const compliment8bit = number => number < 128 ? number : -(256 - number);

Upvotes: 1

Bergi
Bergi

Reputation: 664599

In two's complement, you first need to decide whether the number is complemented or not. Since all parsing functions work with a minus instead of two's complement representation, we need to parse a positive/unsigned number and do some fiddling. If the input is not complemented (starts with 0), it's trivial, otherwise we have three choices:

  • complement the bit string, parse to a number, complement the number back to the intended value:

    console.assert(input.length == 2);
    console.assert(input[0] == '1');
    const compl = input.replace(/[01]/g, function(d){return +!+d;});
    const num = parseInt(compl, 2); // or Number('0b' + compl);
    return ~num; // or -(num + 1) or -num-1
    
  • extend to 32 bit, parse to a number, and cast to a signed 32 bit number with the builtin bitwise operators:

    console.assert(input.length == 2)
    console.assert(input[0] == '1');
    const input32 = "1".repeat(30)+input;
    const num = parseInt(input32, 2); // or Number('0b' + input32);
    return num >> 0; // or ~~num or num | 0
    
  • implement the wrap-around by subtraction (which can be combined with the non-complement case to a modulo operation to avoid branching):

    console.assert(input.length == 2);
    console.assert(input[0] == '1');
    const num = parseInt(input, 2); // or Number('0b' + input);
    return num - 4; // 2²
    

Upvotes: 1

Related Questions