public class test {
public static void main(String[] args) {
byte a=(byte)127, b=2;
byte c=(byte)(a*b);
System.out.println(c);
}
}
为什么结果是
-2
?public class test {
public static void main(String[] args) {
byte a=(byte)127, b=2;
byte c=(byte)(a*b);
System.out.println(c);
}
}
-2
?因为a * b
将导致一个临时的int变量,即254,它是1111 1110。当转换为byte时,这将被处理为signed值。MSB为1,所以它的值将是负数,值为-(((inv)111 1110) + 1) = -((000 0001) + 1) = -2。
a * b
等于 254,那么你的代码应该是:
byte c=(byte)254;
十进制数 254 对应的二进制数是 11111110,也就是 -2。为什么呢?
首先,这个数是负数,因为它以 1 开头(补码表示),然后:
¬ 1 1 1 1 1 1 1 0
是 0 0 0 0 0 0 0 1
。
0 0 0 0 0 0 0 1
1 +
---------------
0 0 0 0 0 0 1 0
这个数在十进制下表示为2,但要记住最高有效位(MSB)是1。因此最终结果是-2。
8位二进制中的127表示为:
01111111
乘以2,你就得到了这个:
11111110
在十进制中,当你乘以10时,所有数字都可以向左移动到下一个位置。同样,在二进制中,当你乘以2时也是如此。
Java使用2的补码来表示负数。基本上,最左边的位是符号位(0表示正数,1表示负数)。要将正数转换为负数,翻转所有位并加一。
例如:00000010
= 2,翻转位:11111101
,然后加一:11111110
= -2。这与上面的127 * 2相同。
因为字节是有符号的,而不是无符号的。
254 = FE = 1111 1110
第一个 '1'
表示该数字为负数。
我认为你想问的是为什么8位有符号整数溢出后会变成负数。
因为在CPU中,没有8位ALU,所以8位将被扩展到32位,在操作后,将低8位返回给用户。
在CPU中:0000_007F * 0000_0002 = 0000_00FE
这是有符号8位的溢出,但值已经计算出来了。
所以返回的值是FE
。
对于8位有符号数,FE
是-2
。