JavaScript 位移动运算的奇葩特性
本文中
a
的取值范围是[-2147483648, 2147483647]
,b
为非负整数
是因为对于位移动运算 a << b
或 a >> b
,如果右操作数 b >= 32
,则只会取 b
的最低五个二进制位进行运算(相当于 b % 32
)。
所以整数左移/右移32位,相当于左移/右移0位,仍等于自身:
1 | 3 >> 32; // 3 |
非整数在左移/右移前会先舍去小数点后的部分(注意:不是Math.floor
!详见JS的向下取整确切来讲,是 Math.trunc
)再进行运算,因此:
1 | a >> 32 === Math.trunc(a); |
在其他语言中的测试:
令 p = 180
,q = -66
(分别为大于0和小于0的随机整数)
Python 2:
1
2
3
4p >> 32 # 0, sign(p)
q >> 32 # -1, sign(q)
p << 32 # 773094113280, Big Integer
q << 32 # -283467841536, Big IntegerPython 3: The same as Python 2
php:
1
2
3
4echo $p >> 32; // 0
echo $q >> 32; // -1
echo $p << 32; // 773094113280, var_dump() returns int
echo $q << 32; // -283467841536, dittoJulia:
1
2
3
4p >> 32 # 0, sign(p)
q >> 32 # -1, sign(q)
p << 32 # 773094113280, typeof() returns Int64
q << 32 # -283467841536C/C++: There's no need to test
perl:
1
2
3
4print(p >> 32); # 0
print(q >> 32); # 4294967295
print(p << 32); # 773094113280
print(q << 32); # 18446743790241710080, I just have no idea about why. Not familiar with perlruby:
1
2
3
4print(p >> 32); # 0
print(q >> 32); # -1
print(p << 32); # 773094113280
print(q << 32); # -283467841536Java: I have no java development env on my Mac
综上,似乎只有 JS 有这种令人迷惑的”取最低五位“行为。(不过 Perl 的 -66 << 32
也挺迷惑的)