JavaScript 按位掩码
JavaScript Bitwise Masking
此题与this other question相似;但是,我想了解为什么它会按原样工作。
以下代码:
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));
Returns:
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 Style Type Cast From Signed To Unsigned
这是一个解决方案,它通过提供实用函数来将 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.
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中,所有按位运算(以及其中的&
)return signed 32-bit integer as a result,范围在-231到231−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
。
此题与this other question相似;但是,我想了解为什么它会按原样工作。
以下代码:
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));
Returns:
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 Style Type Cast From Signed To Unsigned
这是一个解决方案,它通过提供实用函数来将 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.
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中,所有按位运算(以及其中的&
)return signed 32-bit integer as a result,范围在-231到231−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
。