Java如何将int转换为字节?

int i =132; byte b =(byte)i; System.out.println(b); 

输出是-124

这是为什么? 我知道这是一个非常基本的问题,但是我仍然无法对其进行映射,或者了解这是怎么回事?

在Java中, int是32位。 一个byte是8 bits

Java中的所有东西都是有符号的,而byte s, int s, long s是用二进制补码编码的。

在这个数字表格中,最重要的位指定了数字的符号。 如果需要更多位,则最高有效位(“MSB”)将被复制到新的MSB。

所以如果你有字节25511111111并且你想把它表示为一个int (32位),那么你只需要简单地将1复制到左边24次。

现在,读取负数的二进制数的一种方法是从最低有效位开始,向左移动,直到find第一个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读取为正值。

为了理解它是如何工作的,我们需要知道计算机的工作原理。

基数10 (十进制)中的132是基数2 (二进制)中的10000100 。 由于Java以32位存储int ,所以我们拥有的是

  00000000_00000000_00000000_10000100 

当一个int被转换成一个byte ,Java会截断最左边的24位。 我们得到的是10000100

在二进制补码中 ,最左边的位用作符号。 如果最左边的位是0 ,则不会做任何进一步的处理。

如果最左边的位是1 (就像我们这里所说的那样),这意味着这个数字是负数,需要做更多的工作。 为了得到这个幅度,我们减去一个然后应用补码 (应用补码意味着我们反转比特):

  1. 10000100 – 1 = 10000011

  2. 反转10000011 = 01111100

当解释为十进制数时,是01111100 ,是124。

所以我们有一个124的负数,给我们-124

Java中的字节是有符号的,所以它的范围是-2 ^ 7到2 ^ 7-1 – 也就是-128到127.因为132在127以上,所以最后到132-256 = -124。 也就是说,基本上256(2 ^ 8)被添加或减去,直到它落入范围。

欲了解更多信息,您可能需要阅读补充 。

132在-128到127(Byte.MIN_VALUE到Byte.MAX_VALUE)的字节的范围之外。相反,在这种情况下,8位值的最高位被视为负值。 所以这个数字是132 – 256 = -124。

通常在书中,你会发现从模拟到字节的解释是由模数分割执行的。 这不是严格正确的,如下所示实际发生的是,如果剩下的最左边的位被设置,那么来自整数的二进制值的24个最高有效位被舍弃,

 public class castingsample{ public static void main(String args[]){ int i; byte y; i = 1024; for(i = 1024; i > 0; i-- ){ y = (byte)i; System.out.print(i + " mod 128 = " + i%128 + " also "); System.out.println(i + " cast to byte " + " = " + y); } } } 

这是一个非常机械的方法,没有分散注意力的理论:

  1. 将数字转换为二进制表示(使用计算器可以吗?)
  2. 只复制最右边的8位(LSB)并丢弃其余部分。
  3. 从步骤#2的结果来看,如果最左边的位是0,则使用计算器将该数字转换为十进制。 这是你的答案。
  4. 否则(如果最左边的位是1),你的答案是否定的。 保留所有的最右边的零和第一个非零位不变。 剩下的就是倒过来,就是用1代替1,用0代替1。 然后使用一个计算器转换为十进制,并附加一个负号表示该值为负值。

这个更实用的方法是根据上面的很多理论的答案。 所以,那些还在读这些Java模式的人说,这是绝对错误的,因为我上面提到的4个步骤绝对不是模操作。

二补数方程:

在这里输入图像描述


在Java中, byte (N = 8)和int (N = 32)由上面显示的2s补码表示。

从等式来看, 7对于byte是负的,对于int是正的。

 coef: a7 a6 a5 a4 a3 a2 a1 a0 Binary: 1 0 0 0 0 1 0 0 ---------------------------------------------- int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132 byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124 

模拟其工作方式的快速algorithm如下:

 public int toByte(int number) { int tmp = number & 0xff return (tmp & 0x80) == 0 ? tmp : tmp - 256; } 

这是如何工作的? 看看daixtr的答案。 在他的回答中描述的精确algorithm的实现如下:

 public static int toByte(int number) { int tmp = number & 0xff; if ((tmp & 0x80) == 0x80) { int bit = 1; int mask = 0; for(;;) { mask |= bit; if ((tmp & bit) == 0) { bit <<=1; continue; } int left = tmp & (~mask); int right = tmp & mask; left = ~left; left &= (~mask); tmp = left | right; tmp = -(tmp & 0xff); break; } } return tmp; } 

从概念上说,重复减去256是你的号码,直到它在-128到+127的范围内。 所以在你的情况下,你从132开始,然后一步到达-124。

在计算上,这相当于从原始数字中提取8个最低有效位。 (并且注意这8个中最重要的一点是符号位。)

请注意,在其他语言中,这种行为没有定义(例如C和C ++)。

  N is input number case 1: 0<=N<=127 answer=N; case 2: 128<=N<=256 answer=N-256 case 3: N>256 temp1=N/256; temp2=N-temp*256; if temp2<=127 then answer=temp2; else if temp2>=128 then answer=temp2-256; case 4: negative number input do same procedure.just change the sign of the solution