添加后出现意外结果

时间:2018-12-27 00:48:46

标签: java bit-manipulation bitmask

我现在正在用Java编写个人项目,最近我第一次使用位操作。我试图将两个字节转换为短字节,一个字节为高8位,另一个字节为低8位。

运行下面的第一行代码时遇到错误。

错误的结果

short regPair = (short) ( (byte1 << 8) + (byte2) );

正确的结果

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

预期结果是:AAAAAAAABBBBBBBB,其中A代表byte1的比特,B代表byte2的比特。

使用第一行代码,我得到的是在位移后的字节1和字节2之间的典型加法。

错误结果示例

byte1 = 11, byte2 = -72

result = 2816 -72
       = 2744

使用产生预期结果的代码行时,我可以得到3000的正确答案。我很好奇byte2为何需要位屏蔽。我的想法是,它将byte2转换为加法之前的二进制,然后对两个字节执行二进制加法。

4 个答案:

答案 0 :(得分:3)

在错误的情况下,由于byte2运算符,int被提升为+。这不仅意味着在byte2的二进制表示形式的开头添加一些零。由于整数类型用Java中的two's complement表示,因此将添加 1s 。升级后,byte2变为:

1111 1111 1111 1111 1111 1111 1011 1000

通过执行& 0xFF,您将升级强制为int ,然后保留最低有效8位:1011 1000,并使其他所有内容均为0。

答案 1 :(得分:1)

直接打印中间值以查看发生了什么。喜欢,

System.out.printf("%d %s%n", ((byte) -72) & 0xFF, Integer.toBinaryString(((byte) -72) & 0xFF));

我明白了

184 10111000

所以正确的代码实际上是加184(不减去72)。

答案 2 :(得分:0)

因此,我完全忘记了byte是用Java编写的,因此,使用此数据类型的变量执行数学运算时,它将使用带符号的解释,而不是位的直接值。通过执行byte2 & 0xFF,Java将带符号的字节值转换为无符号的int,除了前8位外,其他所有位均设置为0。因此,您可以正确执行二进制加法。

有符号字节值0x11111111 = -1

无符号字节值0x11111111 = 255

答案 3 :(得分:0)

  

在两种情况下,当以下情况时,字节值都在表达式中提升为int   它被评估。

byte byte1 = 11, byte2 = -72;
short regPair = (short) ( (byte1 << 8) + (byte2) );

(2816)+(-72)= 2744

甚至在下面的表达式中,字节也被提升为int

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

2816 + 184 = 3000

在此表达式中,没有两个字节的串联,就像在上面的问题AAAAAAAABBBBBBBBBB中表示的那样,其中A代表字节1中的位,B代表字节2中的位。

实际上-7和255给出184,将其加到2816上得到3000。