JavaScript按位屏蔽
这个问题与其他问题类似, 不过,我想了解为什么这样工作。
以下代码:
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
这是怎么回事?
预先感谢您的帮助。
感谢下面的回应者和评论者,以及以下来源:
- http://speakingjs.com/es5/ch11.html
- JavaScript C风格types从签名转换为无符号
这是一个解决scheme,通过提供工具函数来将基数为16的32位数字转换为带符号的32位整数:
// Convert 'x' to a signed 32-bit integer treating 'x' as a radix-16 number // cf 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 // cf https://stackoverflow.com/questions/14890994/javascript-c-style-type-cast-from-signed-to-unsigned 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整数行为的一些很好的学习。
在JavaScript中,所有按位运算(和其中的&
)都返回有符号的32位整数,结果在-2 31到2 31 -1(含)范围内。 这就是为什么你现在有多一点( 0xde000000
大于0x7ffffff
)表示一个符号,这意味着你会得到一个负值。
一个可能的修复:
var r = 0xdeadbeef & 0xff000000; if (r < 0) { r += (1 << 30) * 4; } console.log( r.toString(16) ); // 'de000000'
因为按位操作(如&
)是在javascript中的带符号的 32位整数完成的。 所有位被设置的0xFFFFFFFF
实际上是-1
,而你期望的0xde000000
实际上是-570425344
。