- 数字在底层存储都是32位的,long是64位
- 左移没有符号,右移才会有符号
反码和补码
System.out.println(Integer.MAX_VALUE);会输出2147483647,换成二进制表示就是01111111111111111111111111111111,也就是。
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
print(Integer.MAX_VALUE);
}
private static void print(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
}
Q:为什么最高一位是0?
A:如果是无符号数字,例如在C++里无符号整数,可以表示0~的数。但是在Java中,是有符号数,可表示的范围为~,也就是说一半分给负数,一半分给正数。就造成了有符号整数没有无符号整数大。
Q:为什么要-1?
A:最高位是0,表示这个数肯定是非负的。最高位是1,代表肯定是负数,值是由后面的位取反,再+1。当这个数位非负时,可表示的数就是的数,为啥要-1呢?不然咋表示0?0是算在非负范围内,因为0的二进制所有位全是0,因为有0,这个最终所有数的范围,就要-1,也就意味着最大值比最小值的绝对值少1。
例如
-1,二进制就是11111111111111111111111111111111,最高位的1代表为负数,其余为取反,则均为0,再+1,为1,值就为1,和符号位结合,最终带符号的数值就为-1。
Q:负数怎么表达?
A:最高位为1,剩下随便用。
Q:负数为啥要取反加一?
A:所有算数符号底层都是用二进制进行计算,例如加减乘除或与反,底层使用一套逻辑。如果负数不用取反加一,则意味着,加和减需要两套逻辑去处理。如果用一套逻辑,性能将会提升,简单高效,所以负数的二进制定义,才会如此扭曲。只能讲到这了,不能再展开了,简单理解,人家乐意。
右移
>>:最高位用符号位补齐,符号位是啥就补啥。>>>:不带符号右移,用0补齐
取相反数
例如5,取相反数为-5。
- 直接加减号
int a = 5;
int b = -a;
System.out.println(b);
- 取反加一
int a = 5;
int c = (~a + 1);
System.out.println(c);
间接证明了上面加减乘除使用一套逻辑。
Q:最小的那个数,取相反数是啥?众所周知,非负数的范围是比负数少1的,那也就意味着最小值的相反数,没有与之对应的正数来表示,那么会是啥呢?
A:其实还是跟算相反数的逻辑有关。最小值的二进制状态,最高位是1,其余全是0。那取反加一后的值,一直进位,回去了,还是它自己,所以最小值的相反数还是它自己。
这不是bug,所有语言都这样。如果真的要用Integer的最小值取相反数,那么你应该用long类型。
最小值:100000000...
取反:01111111.....
加1:100000000....