Reputation: 1813
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
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
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