java中的数字都是以补码的形式出现
java中的byte要转为数字也是以补码的形式进行的转换
=================================================
负数的补码 = 原码的符号位不变其余位取反后加一
=================================================
特别的数字
有两个数字的补码等于本身:一个是0,另一个为该比特内可表示有符号位区分的二进制形式的最大负数(即1000...)。
0的补码计算方式(以8位为例)如下:先计算它的反码:
1111 1111
再将反码加一:
0000 0000,溢出比特二进制值 = 1(二进制)
忽略溢出,其结果为0(0是唯一计算补码过程中会出现溢出的数字。)。因此0的补码为0。而0 x (-1) = 0,因此其补码仍满足“数字a的补码为 -a”的原则。
若计算1000 0000(这是8位内可表示有符号位区分的二进制形式的最大负数-128)的补码:先计算它的反码:
0111 1111
再加一就是它的补码。
1000 0000
1000 0000 (-128)的补码仍为1000 0000 (-128)。但(-128) x (-1) = 128,因此其补码是以上规则的例外。
总结:由于0可以等于0的二补数-0,以及同样因为8位的二补数可显示的值范围为 -128 ~ 127,但-128的二补数128无法用在已有比特数量为8的比特数量内的可用二补数表示。【在计算其他位数内的可表示有符号位区分的二进制形式的最大负数(即1000...000)时,也会有类似情形。】
所以:0和-128的确是“数字a的补码为 -a”原则中两个特别的数字。
=================================================
// -128原码:1000 0000 0000 0000 0000 0000 1000 0000
// -128反码:1111 1111 1111 1111 1111 1111 0111 1111
// -128补码:1111 1111 1111 1111 1111 1111 1000 0000
System.out.println(Integer.toHexString(-128));
// ffffff80
// (-128 & 0xFF)补码:
1111 1111 1111 1111 1111 1111 1000 0000
& 0000 0000 0000 0000 0000 0000 1111 1111
= 0000 0000 0000 0000 0000 0000 1000 0000
System.out.println(Integer.toHexString(-128 & 0xFF));
// 00000080
// byte byte_128 = (byte) -128 ( --> -128补码保留最后8位 --> 1000 0000 )
// byte_128补码:1000 0000
// byte_128反码:1111 1111 ( 符号位不变其余位取反 )
// byte_128原码:1000 0000 ( 补码取原码 = 补码的补码 )
System.out.println(byte_128);
// -128
// byte byte128 = (byte) 128 ( --> 128补码保留最后8位 --> 1000 0000 )
// byte128补码:1000 0000
// byte128反码:1111 1111 ( 符号位不变其余位取反 )
// byte128原码:1000 0000 ( 补码取原码 = 补码的补码 )
System.out.println(byte128);
// -128
// byte byte233 = (byte) 233 ( --> 233补码保留最后8位 --> 1110 1001 )
// byte233补码:1110 1001
// byte233反码:1001 0110 ( 符号位不变其余位取反 )
// byte233原码:1001 0111 ( 补码取原码 = 补码的补码 )
System.out.println(byte233);
// -23