【问题标题】:JavaScript Bitwise MaskingJavaScript 位掩码
【发布时间】:2015-02-14 20:00:20
【问题描述】:

这个问题类似于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));

返回:

ef
be00
ad0000
-22000000
ef
beef
adbeef
-21524111

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

ef
be00
ad0000
de000000
ef
beef
adbeef
deadbeef

这是怎么回事?

提前感谢您的帮助。


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

这是一个解决方案,它通过提供实用函数来将 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. 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 node.js bit-manipulation tostring parseint


    【解决方案1】:

    在 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'
    

    【讨论】:

    • 嗯,您并没有真正松开这一点,但它代表的东西与您的预期不同。
    • 感谢您的意见(@Bergi 也是)。这真的很有帮助,我已经编辑了我的问题以包含一个可行的解决方案。
    【解决方案2】:

    因为按位运算(如&amp;)是在javascript 中对有符号 32 位整数进行的。 0xFFFFFFFF,所有位都设置了,实际上是-1,而你期望的0xde000000实际上是-570425344

    【讨论】:

    • 感谢您的意见。这真的很有帮助,我已经编辑了我的问题以包含一个可行的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    相关资源
    最近更新 更多