好吧,我很困惑,这并不比我想象的容易......我想将二进制补码二进制字符串转换为适当的数字:
-5 = '11111011' 根据 维基百科
所以我认为下面的代码会返回负数 5,但事实并非如此。读完维基百科后,似乎我所要做的就是减去一,然后反转位:
~(parseInt('11111011', 2) - 1)
但它返回-251。令人困惑...
请注意,我将处理许多奇数位长度,并且全部不会都是 8 位。
经过一段时间的研究,我创建了这个解决方案...如果您有二进制和按位运算的经验,请告诉我您的想法:
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') 返回 -5
这将采用未知的位模式 <= 32 bits and if it is < 8 bits convert to positive int and if >= 8,前导 1,负符号整数。
技巧是在 parseInt 之前填充到 32
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);
我感觉到你的困惑。维基百科文章向您展示了 8 位数字的示例,但您通常不会在 javascript 中处理 8 位数字。如果您想在 javascript 中探索二进制数数学,您可能会使用 32 位并使用按位运算符强制对话为 32 位整数。
所以翻译维基百科文章会给你这个:
-5 看起来更像
11111111111111111111111111111011
所有这些额外的零都会被翻转。考虑到这一点,这就更有意义了:
let str = "11111111111111111111111111111011"
console.log(str.length, 'bits')
console.log((parseInt(str, 2) >> 0))
现在应该更有意义了:
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)
这对于将存储在数字(如 251 (11111011))而不是字符串(如“11111011”)中的补码转换为数字更有用。 这适用于任何小于 4294967295 的值(又名 0xffffffff、又名 11111111111111111111111111111111、又名 32 位最大无符号整数值-that-you-dont-want-want-hit-or-you-have-a-big -problem®) (输入的补码,而不是输出数字。)
// 32 bits of ones ( The max value that can be used with bitwise operators without bigInts)
const allOnes = 0xffffffff;
// The amount of bits is required to find the value of the "first bit" because the values are stored as 32 bit values
function decodeTwosComplement(value, bits) {
// Just pad the value with 1s
return value & (1 << (bits - 1) !== 0) ?
(allOnes << bits) | value :
value;
}
function decodeTwosComplementFromString(value) {
return decodeTwosComplement(parseInt(value, 2), value.length);
}
console.log("11111011(-5):", decodeTwosComplementFromString("11111011"));
console.log("001011100(92):", decodeTwosComplementFromString("001011100"));
console.log("11111011(-5, from number):", decodeTwosComplement(0b11111011,8));
console.log("001011100(92, from number):", decodeTwosComplement(0b001011100,9));