为什么 (52 & (1 << 37)) return 0?

Why doesn't (52 & (1 << 37)) return 0?

我正在尝试制作一个算法,给定一个整数,吐出其二进制形式的字符串表示形式。

现在,我基本上是在比较掩码以查看在何处附加 1/0 位。这工作正常,直到出现稍大的数字,例如:(52 & (1 << 37)) 如果我正确理解位移运算符(显然我没有理解)应该 return 0,因为 (1 << 37) = 1 和 37 * 0 的。上次我查了一下,二进制格式的小数点第38位52没有1,为什么这个return32?

整个表达式使用 32 位数执行,因为所有操作数都是 int 值。

因此 1 << 37 不是“一”后跟 37 个“零”位。

事实上,JLS 15.9 表示移位计数被 0x1f 屏蔽(对于 32 位移位运算符)。因此 1 << 37 实际上与 1 << 5 意思相同;即“一”后跟 5 个“零”位。

如果要在移位表达式中使用64位整数,第一个操作数必须是long;即 (52 & (1L << 37)).

在java中,Integer是32位表示(不考虑32位或64位架构)。

当使用 long 时,以下将按预期给出 0(37 < 64):

    (52 & (1L << 37))

对于 long,对于大于 63(更具体地说大于 (1 << 63) - 1))的移位,同样的问题会出现

现在考虑为什么答案是 32 整数:

   1 << 31 == Integer.MIN_VALUE
   
   (1 << 32) - 1 == 0

   1 << 32 == 1 == 2^(32 - 32) == 2^0

   1 << 33 == 2 == 2^(33 - 32) == 2^1

   1 << 34 == 4 == 2^(34 - 32) == 2^2
   
   1 << 37 == 32 == 2^(37 - 32) == 2^5

因为 Java 语言规范说 left-shifting(旧的,但这些东西变化不大)

If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

所以在32位ints上操作时,你代码中的<< 37变成了<< 5,而52 & (1 << 5)实际上是32