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

vad*_*lim 55 javascript bitwise-operators

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

我理解按位SHIFT操作执行此操作:

x << y AS x * 2y

而代字号~运算符可以:

~x AS -(x+1)
Run Code Online (Sandbox Code Playgroud)

所以,我假设如下:

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

它应该导致0.3125.

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

什么是逐步解释?这种操作组合如何以及为什么会导致1342177280而不是0.3125

(这个问题类似于Stack Overflow问题什么是按位运算符?关于按位运算SHIFT符.)

Jar*_*a X 53

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

要准确X << -n与X <<(32-n)不一样......实际上它既简单又复杂......位移算子的有效范围是0到31 ......位移运算符中的RHS首先转换为无符号32位整数,然后用31(十六进制1f)(二进制11111)屏蔽

                   3 = 00000000000000000000000000000011  
                  ~3 = 11111111111111111111111111111100
       0x1f (the mask) 00000000000000000000000000011111
                       --------------------------------
            ~3 & 0x1f  00000000000000000000000000011100 = 28
Run Code Online (Sandbox Code Playgroud)

当幅度小于32时,它与我上面发布的完全相同

位操作使用32位整数.负位移是没有意义的,因此被包含在正32位整数中

<<运算符如何工作

rhs被转换为无符号的32位整数 - 就像这里解释ToUInt32一样

ToUint32基本上取一个数字并返回模数为2 ^ 32的数字

  • @choz实际上它一直回到计算机体系结构.这是因为大多数计算机指令集使用5位来存储移位量(*至少对于MIPS*).特别是这些位是未签名的二进制. (6认同)
  • 你怎么得到`-n`等于`(32-n)`的引用?我并不怀疑这是答案.但是,我只是好奇,因为我找不到一个. (2认同)
  • @choz ...`-n modulo X` =`X - n`当`abs(n)<= X` ...这是我的过度简化 (2认同)

Spe*_*rek 22

~操作者翻转项的位,而<<是按位左移位.以下是二进制步骤中发生的情况.请注意,最左边的位为1表示负数,这种格式是两个赞美:

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)
Run Code Online (Sandbox Code Playgroud)

在最后一行中,位被移位并"旋转"到另一侧,导致大的正数.实际上,通过负数移位类似于按位旋转(溢出位旋转到另一侧),其中通过正数移位不具有这种行为.缺点是忽略了未旋转的位.本质上意味着5 << -4与做法相同5 << (32 - 4),而旋转实际上是一个很大的转变.

其原因是因为位移仅是5位无符号整数.所以二进制文件中的二进制数字是-4 (11100)无符号的28.


hkB*_*Bst 9

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

ECMAScript标准对此进行了解释(在大多数现代机器中,NB使用二进制补码表示在内存中表示正整数和负整数):

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. 通过shiftCount位返回左移lnum的结果.结果是带符号的32位整数.


Mr_*_*uet 7

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

x << y是左移算子(左边).你的数学解释是正确的:)

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


Yel*_*yev 6

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

重要的是:将x << y转换为x*2 y,但它不是直接用法,它只是一个有用的副作用.
此外,如果你有负面y,它不会以相同的方式工作.