1

我在搞乱按位运算符,我试图将一个负字节转换为一个无符号的 8 位值,这就是人们建议的:

System.out.println(-20 & 0xFF); //bitwise AND on negative number and 255 

所以,这完美地工作,并返回 236,但为什么呢?就我而言:

00010100 //binary representation of -20
11111111 //binary representation of 0xFF or 255
--------
00010100 //it returns the same exact thing, so it's either -20 or 20

为什么它有效?我想我错过了一些非常简单的东西,但我似乎无法掌握它。

此外,如果我使用低于 256 的正数执行此操作,它会返回相同的数字。我似乎无法理解 Java 对这些数字的作用。

4

2 回答 2

4

Java 中的文字是int. 因此,当您说 时-20 & 0xFF,会发生以下情况:

  11111111 11111111 11111111 11101100 //-20 -ve nos are stored in 2's compliment form
& 00000000 00000000 00000000 11111111 // 0xFF 
  -------- -------- -------- --------
  00000000 00000000 00000000 11101100 // 236

由于负值以 2 的补码形式存储,因此您得到的值为 236。

当您执行时20 & 0xFF,会发生这种情况:

  00000000 00000000 00000000 00010100 // 20 -ve nos are stored in 2's compliment form
& 00000000 00000000 00000000 11111111 // 0xFF 
  -------- -------- -------- --------
  00000000 00000000 00000000 00010100 // 20
于 2013-04-27T13:16:49.207 回答
1

一个字节是一个 8 位的有符号值,可以在 -128 到 127 的范围内。

最左边的位用作符号位。

System.out.println(-20 & 0xFF);与字节无关,这是一个int操作。

-20的二进制表示,作为一个字节是:1110_1100

1110_1100 & 1111_1111 = 1110_1100

如果您想要未签名,则可以使用 char,但您不会高兴。实际上,Java 没有无符号。

负数以“2s Complement”形式存储,例如:

1111_1111 == -1

但为什么?

2s补码下做负数,所有位翻转(1s补码)加1(2s补码-两次操作)

所以

 0000_0000 - Zero
-0000_0001 - minus one
 ---------
 1111_1110 - Ones complement - (this would be xor 1111_1111)
+0000_0001 - plus one - we're converting to 2s complement, not doing math
 ---------
 1111_1111 - -1 in 2s complement
于 2013-04-27T13:03:58.760 回答