JAVA中的位运算符 与(&)、非(~)、或(|)、异或(^)、左移、有符号右移、无符号右移

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值