JAVA中int数据类型占4个字节,1个字节为8位(bit),所以一个int数据类型的二进制为32位。
1、位与运算符(&)
运算规则:两个数都转为二进制,然后从高位开始比较,如果两个数都为1则为1,否则为0。
比如:129&128,结果为:128
129的二进制为:00000000 00000000 00000000 10000001
128的二进制为:00000000 00000000 00000000 10000000
从高位开始比较得到,得到00000000 00000000 00000000 10000000,即128。
2、位非运算符(~)
运算规则:如果位为0,结果是1,如果位为1,结果是0。
比如:~10,结果为:-11
10的二进制为:00000000 00000000 00000000 00001010
按位取反后为:11111111 11111111 11111111 11110101(补码)
因为按位取反后为负数,计算十进制的实际值时,要做转化,具体转化规则,请参考:https://blog.csdn.net/cinling123/article/details/103669475
反码为:11111111 11111111 11111111 11110100
原码为:10000000 00000000 00000000 00001011
其中原码的最高1为符号位,1011的值为11,最终得出:-11。
3、位或运算符(|)
运算规则:两个数都转为二进制,然后从高位开始比较,两个数只要有一个为1则为1,否则就为0。
比如:129|128,结果为:129
129的二进制为:00000000 00000000 00000000 10000001
128的二进制为:00000000 00000000 00000000 10000000
从高位开始比较得到,得到00000000 00000000 00000000 10000001,即129。
4、位异或运算(^)
运算规则:两个数转为二进制,然后从高位开始比较,如果相同则为0,不相同则为1。
比如:10^11,结果为:1
10的二进制为:00000000 00000000 00000000 00001010
11的二进制为:00000000 00000000 00000000 00001011
从高位开始比较得到的是:00000000 00000000 00000000 00000001,即1。
5、左移运算符(<<)
含义:将运算符左边的对象向左移动运算符右边指定的位数(在低位补0)。
比如:10<<3,结果:80
10的二进制为:00000000 00000000 00000000 00001010
左移后二进制:00000000 00000000 00000000 01010000
快速计算方法:num<<n,相当于num乘以2的n次幂。
6、有符号右移运算符(>>)
含义:将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1。
比如:10>>2,结果:2
10的二进制为:00000000 00000000 00000000 00001010
右移后二进制:00000000 00000000 00000000 00000010
比如:-10>>2,结果:-2
10的二进制为:11111111 11111111 11111111 11110110
右移后二进制:11111111 11111111 11111111 11111101
快速计算方法:num>>n,相当于num除以2的n次幂后取整。
7、无符号右移运算符(>>>)
含义:将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0。
如果是正数,无符号右移与有符号右移一样
比如:10>>>2,结果:2
我们重点说一下负数,区别在于,无符号右移,高位补0,有符号右移,高位补1。
比如:-10>>>2,结果:1073741821
10的二进制为:11111111 11111111 11111111 11110110
右移后二进制:00111111 11111111 11111111 11111101
重点是什么时候用
我为什么要它?
答案1:位运算的运算效率比直接对数字进行加减乘除高很多(至于为什么会快,不明白的可以去搜下为什么C的代码执行速度比Java,python快),代码需要考虑性能的时候。
答案2:因为大牛都喜欢这样,估计是炫技吧!
使用场景
场景1:判断奇偶数 a&1,结果为 0 ,a就是偶数; 结果为 1 ,a就是奇数。
场景2:求平均数 (x+y)/2 这样吗?考虑过 x+y可能超过int的范围吗?正确的姿势是 (x&y)+((x^y)>>1)
场景3:有两个int类型变量x、y,要求两者数字交换,不用临时变量?(当年学java的时候这可是奥数级别的题目) x ^= y; y ^= x; x ^= y;
场景4:求绝对值,int abs( int x ) { int y= x >> 31 ; return (x^y)-y ; //or: (x+y)^y }
场景5:取模 a % (2^n) 等价于 a & (2^n - 1),或者,假设要计算11%3的值,那么也可以这样写11&(3-1),值是一样的。
场景6:快速乘法 a * (2^n) 等价于 a << n
场景7:快速除法 a / (2^n) 等价于 a >> n
场景8:求相反数 (~x+1)
特别注意:
如果做左移和右移超过32位怎么办?
1、移位数对32取余,得到余数;
2、余数做为最终的移位数再做运算。
比如 500>>67 怎么算?(就相当于500>>3)
1、先67对32取余 结果是3
2、然后500/8 结果62