'x << ~y'在JavaScript中代表什么?

What does 'x << ~y' represent in JavaScript?

'x << ~y'在JavaScript中代表什么?

我理解按位 SHIFT 操作是这样做的:

x << y AS x * 2y

波浪号 ~ 运算符:

~x AS -(x+1)

所以,我假设如下:

5 << ~3 AS 5 * 2-4 or 5 * Math.pow(2, -4)

结果应该是 0.3125

但是,当我 运行 5 << ~3 结果是 1342177280.

什么是分步说明?这种操作组合如何以及为什么会导致 1342177280 而不是 0.3125

(此问题类似于 Stack Overflow 问题 What are bitwise operators? 关于按位 SHIFT 运算符。)

~x 将反转 x 值的位表示(32 位有符号值和二进制补码)。

x << y 是左移运算符(这里是左移)。你的数学解释是正确的:)

您可以在此处阅读有关按位运算的更多信息:bitwise operators in Javascript

5 << ~3 给出与 5 << -4 相同的结果,你是对的。

重要的是:移动 x << y 确实会导致 x * 2y , 但它不是直接用法,它只是一个有用的副作用。
此外,如果你有一个负数 y,它就不会以同样的方式工作。

~ 运算符翻转项目的位,而 << 是按位左移。以下是二进制中发生的事情。 注意最左边的位为1表示负数,格式为twos compliment:

3         // (00000000000000000000000000000011 => +3 in decimal)
// ~ flips the bits
~3        // (11111111111111111111111111111100 => -4 in decimal)
// The number 5 (..00101) shifted by left by -4 (-4 unsigned -> 28)
5         // (00000000000000000000000000000101 => +5 in decimal)
5 << -4   // (01010000000000000000000000000000 => +1342177280 in decimal)

在最后一行中,位被移动 "rotated" 到另一边,导致一个大的正数。事实上,负数移位类似于按位旋转(溢出的位被旋转到另一侧),而正数移位没有这种行为。缺点是忽略了非旋转位。本质上意味着 5 << -45 << (32 - 4) 相同,而是旋转实际上是一个很大的偏移。

这样做的原因是因为移位只是一个 5 位 无符号 整数。因此,无符号二进制数 -4 (11100)28.

x << -n 等于 x << (32 - n)
~3 == -4 所以
5 << ~3 === 5 << (32 - 4) === 5 << 281,342,177,280

to be accurate X << -n is not the same as X << (32 - n) ... in fact it's both simpler and more complicated ... the valid range of a bit shift operator is 0 to 31 ... the RHS in a bit shift operator is first converted to an unsigned 32 bit integer, then masked with 31 (hex 1f) (binary 11111)

                   3 = 00000000000000000000000000000011  
                  ~3 = 11111111111111111111111111111100
       0x1f (the mask) 00000000000000000000000000011111
                       --------------------------------
            ~3 & 0x1f  00000000000000000000000000011100 = 28

当星等小于32时,它和我上面发布的完全一样

位运算适用于 32 位整数。负移位没有意义,因此被包装成正 32 位整数

<< operator 的工作原理

rhs 被转换为无符号的 32 位整数 - 如此处所述ToUInt32

ToUint32 基本上取一个数字 returns 数字模 2^32

您的分析是正确的,除了您不应将 ~3 (11100)(3 (00011) 的位补码)解释为 -4 ,而是将其解释为无符号(非负)5 位整数,即 28 = 16 + 8 + 4 (11100).

这在ECMAScript standard (NB in most modern machines, positive and negative integers are represented in memory using two's complement表示中有解释:

12.8.3 左移运算符 (<<)

注意按右操作数指定的量对左操作数执行按位左移操作。

12.8.3.1 运行时语义:评估

ShiftExpression : ShiftExpression << AdditiveExpression

  1. 令 lref 为计算 ShiftExpression 的结果。
  2. 设 lval 为 GetValue(lref)。
  3. ReturnIfAbrupt(lval).
  4. 令 rref 为计算 AdditiveExpression 的结果。
  5. 设 rval 为 GetValue(rref)。
  6. ReturnIfAbrupt(rval).
  7. 设 lnum 为 ToInt32(lval)。
  8. ReturnIfAbrupt(lnum).
  9. 设 rnum 为 ToUint32(rval)。
  10. ReturnIfAbrupt(rnum)。
  11. 令 shiftCount 为除 rnum 的最低有效 5 位之外的所有屏蔽的结果,即计算 rnum & 0x1F。
  12. Return lnum 左移 shiftCount 位的结果。这 结果是一个带符号的 32 位整数。