- 原码、反码和补码
一个数可以分成符号位(0正1负)+ 真值,原码是我们正常想法写出来的二进制。由于计算机只能做加法,负数用单纯的二进制原码书写会出错,于是大家发明了反码(正数不变,负数符号位不变,真值部分取反);再后来由于+0, -0的争端,于是改进反码,变成补码(正数不变,负数符号位不变,真值部分取反,然后+1)。二进制前面的0都可以省略,所以总结来说:计算机里的负数都是用补码(符号位1,真值部分取反+1)表示的。 - 位运算和无符号位运算
对于负数而言,普通位运算已然保持了符号位1,而是将真值部分进行位运算。但要注意对于负数的位运算操作是建立在补码上的(补码运算,得到补码结果,将补码结果转换为普通的10进制数结果),所以就会出现-15 >> 1 得到的是-8 而不是 -7.而无符号位运算则是将负数的补码整个一起位移,并且高位补0,这就意味着将高位符号位补0变成了正数,所以最后往往得到一个很大的值,即Integer.MAX_VALUE – x.x为该负数的绝对值进行位运算后得到的结果。 - 大数(long 64,int 32)向小数(short 16,byte 8)的溢出问题
直接进行位运算,默认输出值的类型为int.short, byte等小数将会自动扩充成int进行位运算,long则使用64位位运算。如果强制大数向小数转换,就会出现溢出,原大数真值中的1变成了小数里代表符号位的1而成为了负数。
最后就是位运算在刷题里遇到的不多,有时候那种纯数字的问题不能用乘法除法的话就可以考虑位运算了。