问题
int i =132;
byte b =(byte)i;
System.out.println(b);
输出为-124
这是为什么?我知道这是一个非常基本的问题,但我仍然无法对其进行映射,或者了解这是如何发生的?
#1 热门回答(154 赞)
在Java中,anint
是32位。 Abyte
is 8bits
。
Java中的所有内容都已签名,byte
s,int
s,long
s以二进制编码进行编码。
在此numbercheme中,最重要的位指定数字的符号。如果需要更多位,则将最高有效位("MSB")简单地复制到新MSB。
因此,如果你有byte255
:11111111
并且你想将其表示为int
(32位),则只需将1复制到左侧24次。
现在,读取负二进制补码的一种方法是从最低有效位开始,向左移动直到找到第一个1,然后反转每一位。结果数字是该数字的正数
例如:11111111
goes to00000001
= -1
。这就是Java将显示为值的内容。
你可能想要做的是知道字节的无符号值。
你可以使用位掩码来完成此操作,该位掩码删除除最低8位之外的所有内容。 (0xff的)
所以:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
打印出来:"Signed: -1 Unsigned: 255"
这里到底发生了什么?
我们使用按位AND来屏蔽所有无关的符号位(最低有效8位左侧的1)。当int转换为字节时,Java会截断最左边的24位
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
由于第32位现在是符号位而不是第8位(我们将符号位设置为0,这是正数),因此字节的原始8位由Java读取为正值。
#2 热门回答(78 赞)
要了解它是如何工作的,我们需要知道计算机是按位工作的。
132 inbase 10(十进制)is10000100
inbase 2(二进制)。由于Java以32位存储int
,我们拥有的是
00000000_00000000_00000000_10000100
当aint
转换为abyte
时,Javachops-off最左边的24位。我们得到的是10000100
。
在two's complement中,最左边的位用作符号。如果最左边的位是0
,则不会再进行任何操作。
如果最左边的位是1
(正如我们在这里),则表示该数字为负数,需要完成更多工作。为了得到幅度,我们减去1然后applyone's complement(应用一个补码意味着我们反转位):
- 10000100 - 1 = 10000011
- 反转10000011 = 01111100
01111100
当被解释为十进制数时,是124。
所以我们有一个124的负数,给我们**-124**。
#3 热门回答(22 赞)
Java中的字节是有符号的,所以它的范围是-2 ^ 7到2 ^ 7-1 - 即-128到127.由于132高于127,你最终会回绕到132-256 = -124。也就是说,基本上加上或减去256(2 ^ 8)直到它落入范围。
有关更多信息,你可能需要阅读two's complement。