1.位运算基础补充: 参考:https://blog.csdn.net/pcwl1206/article/details/86552701
(1)机器数:二进制最高位存放符号,正数0,负数-1
(2)反码:正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反
(3)补码:且计算机中保存和展示是补码,计算机中的位运算都是用补码进行的,所有运算结果都是补码,正数补码是原码,负数补码是反码+1
(4)位运算:
i**:左移**:m<<n,将十进制m的二进制数向左移动n位,高位溢出的全部舍弃,低位补0,结论:在位数不溢出的情况下 移动之后的数字结果为m*2^n
//左移运算
int q =5<<3;
System.out.println(Integer.toBinaryString(q));//101000
ii:右移: m>>n,如果m是正数则高位补0,低位移除舍弃,如果m是负数,则高位补1,m >> n 即相当于 m 除以 2 的 n 次方,得到的为整数时,即为结果。如果结果为小数,此时会出现两种情况:
如果 m 为正数,得到的商会无条件的舍弃小数位; 5>>2结果为5/4=1
如果 m 为负数,舍弃小数部分,然后把整数部分加+1得到位移后的值。
int f=-5>>2;
System.out.println(f);//补码:11111111111111111111111111111110(-2)
iii:无符号右移(>>>) m >>> n:整数 m 表示的二进制右移 n 位,不论正负数,高位都补 0
-5 >>> 2:把十进制的数值 -5 右移两位,把 -5 转为 16 位的二进制机器数:11111111 11111111 11111111 11111011
按右移原理,将二进制数右移两位:00111111 11111111 11111111 11111110
右移后结果为正数。
(5)&与运算:两个数的二进制表示:同位数都为1则为1,否则为0,and的效果
(6)非~运算:1变0,0变1:
int f=~5;
System.out.println(Integer.toBinaryString(f));11111111111111111111111111111010(-6)
(7)按位或操作(|)有1为1,其他为0
(8).按位异或操作( ^ )相同为0,不同为1,异或有个作用就是判断两个数值是否相等,m^n0,则mn,否则不相等;
eg:两个数交换位置原理:
int a = 1;//0001
int b = 2;//0010
//两个数交换原理
a=a^b;//0011 //a和b异或的结果
b=a^b;//0001 //结果又跟b进行异或,将结果中跟b相同的位数全变为0,剩下的就是a
a=a^b;//0010 //将结果跟a异或,剩下的就是b
2.位运算的优先级 注意位移运算在位运算之前,而赋值在最后
eg:
int result = 0;
result += (bytes[0]&0xff)<<24; //不加括号不行
ps : java中位运算都是用补码来进行的
eg:
System.out.println(Long.toBinaryString(-1L)); // 32个1 后5位:11111
System.out.println(Long.toBinaryString(-1L<<5));//左移5位后 后5位为:000000 ,高位溢出的直接舍弃
System.out.println(new Long(-1L^(-1L<<5)));//异或运算之后,后5位为11111,即十进制31