int i =132;
byte b =(byte)i; System.out.println(b);
输出为-124
这是为什么?我知道这是一个非常基本的问题,但是我仍然无法对其进行映射,或者了解这是如何发生的?
Way*_*yne 168
在Java中,a int是32位.A byte是8 bits.
最原始的类型Java中的签名,byte,short,int,和long被编码在二进制补码.(char类型是无符号的,符号的概念不适用boolean.)
在此数字方案中,最高有效位指定数字的符号.如果需要更多位,则将最高有效位("MSB")简单地复制到新MSB.
因此,如果您有字节255:11111111
并且您希望将其表示为int(32位),则只需将1复制到左侧24次.
现在,读取负二进制补码的一种方法是从最低有效位开始,向左移动直到找到第一个1,然后反转每一位.结果数字是该数字的正数
例如:11111111转到00000001= -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读取为正值.
Pac*_*ier 88
要了解它是如何工作的,我们需要知道计算机是按位工作的.
在132 基座10(十进制)是132在基体2(二进制).由于Java 1000_0100以32位存储,我们拥有的是
0000_0000_0000_0000_0000_0000_1000_0100
当a int转换为a时System.out.println,Java会从最左边的24位中删除.我们得到的是1.
在二进制补码中,最左边的位用作符号.如果最左边的位是System.out.println(int-to-byte(,则不会再进行任何操作.
如果最左边的位))(就像我们这里),则意味着该数字为负数,需要完成更多工作.为了获得幅度,我们减1然后应用一个补码(应用一个补码意味着我们反转位):
0000_0000_0000_0000_0000_0000_1000_0100 -  1 = 1000_0100
反转1000_0100=1000_0011
0111_1100 当被解释为十进制数时,是124.
所以我们有一个负数,数量为124,给我们-124.
Pet*_*rey 16
132超出字节范围-128到127(Byte.MIN_VALUE到Byte.MAX_VALUE)而是将8位值的最高位视为有符号,表示在这种情况下它是负数.所以数字是132 - 256 = -124.
这是一种没有分心理论的非常机械的方法:
这种更实用的方法符合上面的许多理论答案。因此,那些仍在阅读那些Java书籍说要使用模数的人,这绝对是错误的,因为我上面概述的4个步骤绝对不是模数运算。