这是我的代码:
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时,这将作为有符号值处理。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 为底乘以 10 时,所有数字都可以左移到下一个位置。二进制乘以 2 时自然也是如此)
Java 使用 2 的补码来表示负数。基本上,最左边的位是符号位(0 表示 +,1 表示 -)。要将正数转换为负数,请将所有位翻转并加一。
示例:00000010
= 2,翻转位:11111101
,然后加一:11111110
= -2。这与上面的 127*2 相同。
我想你想问的是为什么 8 位有符号整数的溢出会变成负数。
由于CPU没有8bits ALU,所以8bits会扩展为32bits,运算后将低8bits返回给用户。
在 CPU 中:0000_007F * 0000_0002 = 0000_00FE
这是有符号 8 位的溢出,但该值已经计算过了。
所以返回值为FE
.
对于 8 位签名,FE
是-2
.
由于 byte 是有符号类型 2 * 127 是二进制“11111110”,它是-2的二进制补码。
因为字节是有符号的,而不是无符号的。
254 = FE = 1111 1110
第一个'1'
将数字表示为负数。