一文带你深入理解位运算

目录

一. 前言

二. 简介

三. 实操

3.1. &按位与运算

3.2. | 按位或运算

3.3. ^按位异或运算

3.4. ~按位非运算

3.5. <<左移

3.6. >>右移(又称为有符号右移)

3.7. >>>无符号右移

四. 原码、反码、补码

五. 实例


一. 前言

    相信同学们听到“位运算”这个词都很熟悉,但是在实际应用中却很少涉及,上至十几年的老程序员,下至两三年的菜鸟,可能都没有真正弄懂过,今天就带大家深入地理解学习一遍。

程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。运位算包括位逻辑运算移位运算,位逻辑运算能够方便地设置或屏蔽内存中某个字节的一位或几位,也可以对两个数按位相加等;移位运算可以对内存中某个二进制数左移或右移几位等。

二. 简介

Java提供了七种位运算:

 位运算符 名称 含义 举例
 &按位与

将参与运算的两个二进制数进行&与运算,如果两个二进制位都是1,则与运算的结果为1,其他全都为0。(0与任意数N&运算都是0)

a&b
 |按位或

将参与运算的两个二进制数进行|或运算,两个二进制位只要其中1个是1 ,那么就是1,如果2个二进制位都是0则表示0。(0与任意数N|运算都是任意数N)

a|b 
按位异或将参与运算的两个二进制数进行^异或运算,如果2个二进制位都是0或者都是1,那么就是0,如果两个二进制位不同,则为1。a^b
按位非一元操作符,按位取反。每个二进制位上都取相反值,1变成0,0变成1。~a
<< 左移将一个数各二进制位全部向左移动若干位,左移运算没有有符号和无符号左移动,在左移时,移除高位的同时在低位补0a<<2 
>> 右移又称为有符号右移。将一个数各二进制位全部向右移动若干位,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。a>>2 
>>> 无符号右移 将一个数各二进制位全部向右移动若干位,右移之后左边都是补上0。忽略符号位 

a>>>2

由位运算操作符衍生而来的有:
&= 按位与赋值,|=  按位或赋值,^= 按位非赋值,<<= 赋值左移,>>= 右移赋值,>>>= 无符号右移赋值
(和 += 一个概念)

三. 实操

我们以0、1、2、4、8、16、32这几个数来演示下各运算符的逻辑,首先我们计算出这几个数的二进制分别是:

 0  的二进制数为: 0000 0000 0000 0000
 1  的二进制数为: 0000 0000 0000 0001
 2  的二进制数为: 0000 0000 0000 0010
 4  的二进制数为: 0000 0000 0000 0100
 8  的二进制数为: 0000 0000 0000 1000
16 的二进制数为: 0000 0000 0001 0000
32 的二进制数为: 0000 0000 0010 0000

3.1. &按位与运算

将参与运算的两个二进制数进行&与运算,如果两个二进制位都是1,则与运算的结果为1,其他全都为0。(0与任意数N&运算都是0)

判断奇偶:n & 1 == 1则为奇数,n & 1 == 0则为偶数

判断是否是2的整数次幂:n & (n-1) == 0是2 ^ n,n & (n-1) == 1不是2 ^ n

0&2 = 0
0&4 = 0
2&4 = 0
2&8 = 0
4&12= 4

3.2. | 按位或运算

将参与运算的两个二进制数进行|或运算,两个二进制位只要其中1个是1 ,那么就是1,如果2个二进制位都是0则表示0。(0与任意数N|运算都是任意数N)

0|2 = 2
0|4 = 4
2|4 = 6
2|8 = 10

3.3. ^按位异或运算

将参与运算的两个二进制数进行^异或运算,如果2个二进制位都是0或者都是1,那么就是0,如果两个二进制位不同,则为1。

0^2 = 2
0^4 = 4
2^4 = 6
2^8 = 10

3.4. ~按位非运算

一元操作符,按位取反。每个二进制位上都取相反值,1变成0,0变成1。

~0 = -1
~1 = -2
~2 = -3
~4 = -5
~8 = -9

3.5. <<左移

将一个数各二进制位全部向左移动若干位,左移运算没有有符号和无符号左移动,在左移时,移除高位的同时在低位补0

左移1位相当于乘2,x << n等价于x * (2 ^ n)。

2<<1 = 4
2<<2 = 8
2<<3 = 16
2<<4 = 32

3.6. >>右移(又称为有符号右移)

将一个数各二进制位全部向右移动若干位,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。

右移1位相当于除2,x >> n等价于x / 2n。

32>>1 = 16
32>>2 = 8
32>>3 = 4
32>>4 = 2

3.7. >>>无符号右移

将一个数各二进制位全部向右移动若干位,右移之后左边都是补上0。忽略符号位

32>>>1 = 16
32>>>2 = 8
32>>>3 = 4
32>>>4 = 2

四. 原码、反码、补码

一个数,取绝对值大小转换为二进制数,称其为原码。正常情况下,对计算机的俩个数进行加法运算,由于不知道符号,所以对其取补码后进行运算,正数的补码是其本身,负数的补码是对其正数取反加1。
原码:正数的原码是本身,负数的原码是其正数的原码,并将最高位改为1。

以5为例:
5的二进制数(即原码):0000 0000 0000 0101

原码:0000 0101
反码:1111 1010
补码:1111 1011   (负数的补码是对其正数取反加1)
即得到-5的二进制数:1111 1011

五. 实例

把一个整数拆成2的n次方的数相加
public void pow2() {
    int input = 19;
    int m = 1;
    for (int i =1; i< 32; i++) {
        if((m & input) == m) {
            System.out.println(m);
        }

        m = m << 1;
        if(m > input) {
            break;
        }
    }
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流华追梦

你的鼓励将是我创作最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值