Java - 屏蔽符号位会导致意外行为

Java - Masking out sign bit causes unexpected behavior

我有以下值:

int x = -51232;

Java 整数是 32 位,所以在二进制中应该是这样的:

10000000000000001100100000100000

左边的符号位设置为1,因为x是负数。

那我做手术

x = (x & Integer.MAX_VALUE);

Integer.MAX_VALUE2147483647 并且在二进制中是:

01111111111111111111111111111111

左边为0,因为值为正。

那么为什么 x & Integer.MAX_VALUE 会产生 2147432416AND 运算符应该只检索 xInteger.MAX_VALUE 共有的位,这应该等同于 -x (因为它们不共享相同的符号位)。

这是怎么回事?

你的误解是由于不了解负整数在Java中如何用二进制表示造成的。你应该阅读 2 的补码。

10000000000000001100100000100000 而不是 -51232.

的二进制表示

11111111111111110011011111100000是.

当你运行按位与,你得到:

11111111111111110011011111100000 (-51232)
01111111111111111111111111111111 (Integer.MAX_VALUE)
--------------------------------
01111111111111110011011111100000 (2147432416)

这里是-51232的二进制表示紧挨着51232的二进制表示,可以看到它们的和是232。对于任何一对 ints x-x.

,2 的补码总是这种情况
00000000000000001100100000100000 (-51232)
11111111111111110011011111100000 (51232)

整数存储在两个补码中:https://en.m.wikipedia.org/wiki/Two%27s_complement

因此,虽然最左边的位表示负数,但它并不是真正的符号位,因为它是普通表示法中的浮点数。

这种表示的主要原因是它使得在硬件级别进行加法和减法等操作变得容易。

不应该用两个补码表示法,-1 表示所有位都设置为 1。