JavaScript 按位掩码

ptd*_*ker 5 javascript bit-manipulation tostring parseint node.js

这个问题与另一个问题类似;但是,我想了解为什么会这样。

下面的代码:

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));
Run Code Online (Sandbox Code Playgroud)

返回:

ef
be00
ad0000
-22000000
ef
beef
adbeef
-21524111
Run Code Online (Sandbox Code Playgroud)

当我对 .string(16) 的期望是:

ef
be00
ad0000
de000000
ef
beef
adbeef
deadbeef
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

预先感谢您的帮助。


感谢以下回复者和评论者,以及以下来源:

下面是一个解决方案,它通过提供实用函数来将 radix-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. /sf/ask/1042369611/
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')));
Run Code Online (Sandbox Code Playgroud)

这会产生预期的输出:

ef
be00
ad0000
de000000
ef
beef
adbeef
deadbeef
Run Code Online (Sandbox Code Playgroud)

以及我对 JavaScript 整数行为的一些很好的学习。

rai*_*7ow 4

在 JavaScript 中,所有按位运算(以及&其中的运算)都会返回带符号的 32 位整数作为结果,范围为 \xe2\x88\x922 31到 2 31 \xe2\x88\x921(含)。这就是为什么你有额外的位(0xde000000大于0x7ffffff​​),这意味着您会得到一个负值。

\n\n

一种可能的修复:

\n\n
var r = 0xdeadbeef & 0xff000000;\nif (r < 0) {\n  r += (1 << 30) * 4;\n}\nconsole.log( r.toString(16) ); // \'de000000\'\n
Run Code Online (Sandbox Code Playgroud)\n