【问题标题】:Left shift results in negative numbers in Javascript左移导致Javascript中的负数
【发布时间】:2019-08-18 07:07:08
【问题描述】:

我无法理解换档的工作原理。我希望ab 是相同的,但事实并非如此:

a = 0xff000000;
console.log(a.toString(16));
b = 0xff << 24;
console.log(b.toString(16));

导致:

ff000000
-1000000

我在尝试从 4 个字节创建一个 32 位数字时来到此代码。

    标签: javascript


    【解决方案1】:

    按位运算符将其操作数转换为带符号的 32 位数字.这意味着最高有效位是符号位,它只为数值提供 31 位。

    0xff000000 本身被解释为 64 位浮点值。但是将其截断为 32 位有符号整数会产生负值,因为最高有效位是 1

    0xff000000.toString(2);
    > "11111111000000000000000000000000"
    
    (0xff000000 | 0).toString(16)
    > -1000000
    

    根据Bitwise operations on 32-bit unsigned ints?,您可以使用&gt;&gt;&gt; 0 将值转换回无符号值:

    0xff << 24 >>> 0
    > 4278190080
    

    来自spec

    结果是一个无符号的 32 位整数。

    【讨论】:

    • 如果是这种情况,我怎样才能以 64 位进行移位?
    • 您的意思是 0xff000000 被解释为无符号 32 位整数吗?
    • @ic3b3rg:不。JavaScript 只有一种数字类型,64 位浮点。 ecma-international.org/ecma-262/9.0/… 。然而:“一些 ECMAScript 运算符仅处理特定范围内的整数,例如 -2^31 到 2^31-1(含)或 0 到 2^16-1(含)范围内的整数。这些运算符接受 Number 类型的任何值,但首先将每个这样的值转换为预期范围内的整数值。参见 7.1 中对数值转换操作的描述。
    • 我建议说 0x 文字形式更正确解释的作为 x 字节的无符号整数,其中 x 是文字的长度(减去 0x 部分),即 0xH 的范围为 0 - 15(4 位无符号整数)。解释后的数字(与所有 JS 数字一样)存储为 64 位浮点数
    • @ic3b3rg:很公平。规范称之为"HexIntegerLiteral"的确。
    【解决方案2】:

    所以事实证明这是按照规范。位移运算符返回有符号的 32 位整数结果。

    结果是一个有符号的 32 位整数。

    来自the latest ECMAScript spec

    因为您的数字已经是 8 位长,将其左移 24 位,然后将其解释为有符号整数意味着前导 1 位被视为使其成为负数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-01
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多