JavaScript 位掩码

5
这个问题类似于另一个问题,但是我想要理解为什么它能够正常工作。

以下代码:

console.log((parseInt('0xdeadbeef', 16) & parseInt('0x000000ff', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0x0000ff00', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0x00ff0000', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0xff000000', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0x000000ff', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0x0000ffff', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0x00ffffff', 16)).toString(16));
console.log((parseInt('0xdeadbeef', 16) & parseInt('0xffffffff', 16)).toString(16));

返回:

ef
be00
ad0000
-22000000
ef
beef
adbeef
-21524111

当我期望从.string(16)得到的是:
ef
be00
ad0000
de000000
ef
beef
adbeef
deadbeef

这是怎么回事?
非常感谢您的帮助。
感谢下面的回答者和评论者,以及以下来源: 以下是一种解决方法,通过提供实用函数将基数为16位的32位数字转换为带符号的32位整数:
// Convert 'x' to a signed 32-bit integer treating 'x' as a radix-16 number
// c.f. http://speakingjs.com/es5/ch11.html
function toInt32Radix16(x) {
    return (parseInt(x, 16) | 0);
}

// Convert a signed 32-bit integer 'x' to a radix-16 number
// c.f. https://dev59.com/8mUp5IYBdhLWcg3w_rcl
function toRadix16int32(x) {
    return ((x >>> 0).toString(16));
}

console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x000000ff')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x0000ff00')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x00ff0000')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0xff000000')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x000000ff')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x0000ffff')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x00ffffff')));
console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0xffffffff')));

这将产生预期的输出:

ef
be00
ad0000
de000000
ef
beef
adbeef
deadbeef

除此之外,我在JavaScript整数行为方面也有了一些很好的学习。

2个回答

4
在JavaScript中,所有位运算(包括其中的&返回带符号的32位整数作为结果,范围为-231至231-1,包括两个端点。这就是为什么现在有一个额外的位(0xde000000大于0x7ffffff),表示符号,意味着你现在得到的是一个负值。

一种可能的修复方法:

var r = 0xdeadbeef & 0xff000000;
if (r < 0) {
  r += (1 << 30) * 4;
}
console.log( r.toString(16) ); // 'de000000'

1
好的,你并不是真的失去了这个位(bit),但它代表的东西与你预期的不同。 - Bergi
感谢您的回复(@Bergi也是)。这真的很有帮助,我已经编辑了我的问题并包含了一个可行的解决方案。 - ptdecker

1
因为在 JavaScript 中,位运算(例如 &)是在有符号的 32 位整数上进行的。其中,所有位都被设置为 1 的数字 0xFFFFFFFF 实际上是 -1,而您期望的数字 0xde000000 实际上是 -570425344。请注意保留 HTML 标签。

谢谢您的回复。它真的很有帮助,我已经编辑了我的问题并包含了一个可行的解决方案。 - ptdecker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接