Java负数的计算过程
java中最高位表示符号位,0表示正数,1表示负数
根据十进制推算二进制
以-5为例子
- -5的原码:
1000 0101 - 求反码 :
1111 1010,符号位不进行取反 - 求补码(+1):
1111 1011
所以-5用二进制表示为1111 1011
根据二进制逆推十进制
以10001010为例子
-
获取补码,(-1操作)
10001010 - 1 = 10001001 -
获取反码
10001001的反码11110110 -
不看符号位,算出大小
1110110对应的值为118,所以10001010的值就是-118
可以看出来,对于负数而言,因为1000 0000 后七位因为要取反,所以后七位越大反而绝对值越小,例如1111 1111 等于-1,而1111 1110 等于-2
那么对于负数而言 1000 0000 就是绝对值最大,相对值最小的了,等于-128
为什么要这样设计
首先在计算机中减法实际上是加法,2-1 == 2 + (-1),那么进行推理一下
如果都用原码
2 的原码:0000 0010
-1 的原码: 1000 0001
2 + (-1)= 10000 0011
答案是是 -3,答案错误
如果正数用原码,负数用补码
事例1
2原码:0000 0010
-1补码: 1111 1111
相加 =0000 0001 ,就等于1
事例2
10原码:0000 1010
-20补码: 1110 1100
10 + (-20) = 1111 0110 等于-10
为什么要用补码表示负数,而不是反码
或者换个说法,为什么要进行+1操作
如果不用补码,而用反码
1的原码: 0000 0001
-1的反码:1111 1110
1 + (-1) = 1111 1111 = -128
很明显答案错误
那么为什么要进行+1操作,如果你对1111 11111 +1可以发现 = 0001 0000 0000,而因为byte的大小只有8位,第9位要舍弃也就是0000 0000
因为负数最高位存在一个1,也就是说负数天然要比正数多一个1,对于正数而言,你就得额外+1才能保证正数和负数是一样大的。
关于byte取值范围
byte的取值范围为-128 ~ 127
为什么负值要大于正值?
对于最大值很容易得出:0111 1111 就等于127
但是负数不同,在1000 0000这个特殊情况下符号位是参与运算的,也就是说,1000 0000 是最小值,转化成十进制就是-128了
Java代码测试
public static void main(String[] args) {
byte x1 = (byte)0b00000010;
byte x2 = (byte)0b11111111;
System.out.println("x1 = " + x1);
System.out.println("x2 = " + x2);
System.out.println("x1 + x2 = " + (x1 + x2));
byte x3 = (byte)0b11111110;
System.out.println("x3 = " + x3);
byte negative20 = (byte)0b11101100;
System.out.println("negative20 : " + negative20);
byte negative10 = (byte)0b11110110;
System.out.println("negative10:"+negative10);
}