位运算——进阶编程技巧

位运算即基于二进制的运算,是直接对内存数据进行处理的更符合计算机系统的运算。众所周知,计算机系统是基于二进制的,若我们能够在编程的时候使用位运算,则计算机能够更加容易“读懂”,从而大大提高代码运行速度。
虽然位运算与我们日常经常接触的十进制的运算不同,可能会难以理解,但是为了进一步优化代码,我们必须去尝试使用位运算代替部分代码。位运算是前人留给我们的巨大的财富和强大的武器。

本文将介绍位运算的类型以及位运算的一些简单的例子。

位运算类型

  1. 与&
    只有1&1 = 1,其他与运算结果为0,即0&1 = 0;1&0 = 0;0&0 = 0。

  2. 或|
    只有0|0 = 0,其他或运算结果为1,即0|1 = 1 ;1|0 = 1;1|1 = 1。

  3. 非~
    ~0 = 1,~1 = 0。

  4. 异或^
    异或即不同为1,相同为0。即0^0 = 0 1^1 = 0 0^1 = 1 1^0 = 1。

  5. 左移<<
    将二进制数左移n位,低位补0.如下表所示:
    | 左移前 | 0010 1000 |
    | >>3 | 0100 0000 |
    | >>1 | 1010 0000 |

  6. 右移>>
    将二进制数右移n位,若为负数,高位补1;否则,高位补0.
    | 右移前 | 0010 1010 | 1010 1010 |
    | >>2 | 0000 1010 | 1110 1010 |

代码示例

一些有用的小例子~

  • 求两个整数的平均值

&将两个数一样的部分提出来一半,异或将两个数不一样的数提出来了,再右移一位,相当于提出来了一半,将他们相同的和不相同各提出来一半就是平均数。

int avg(int x,int y)
{
    /*位运算求两个整数的平均值*/
    return (x & y) + ((x^y)>>1);
}

一行代码搞定~

  • 求一个整数的绝对值
int abs(int x)
{
    int y = x>>31;//x为正数,则y = 0 ; x 为负数 则 y = -1;
    return ((x^y)-y);
}
  • 交换两个数
int swap(int *a,int *b)
{
    (*a) ^= *b;
    (*b) ^= *a;
    (*a) ^= *b;
    return 0;
}

  • 一些复杂点的例子
unsigned setbits(unsigned x,int p,int n, unsigned y)
{/*将X中从第p位开始的n各位设置为y中最右边n位的值,x的其余各位保持不变*/
    return x&~(~(~0<<n)<<(p+1-n))||(y&~(~0<<n)<<(p+1-n));
}


unsigned invert(unsigned x,int p,int n)
{/*将x从第p位开始的n个位求反,新的其余各位保持不变*/
    return x^(~(~0<<n)<<(p+1-n));
}



unsigned rightrot(unsigned x,int n)
{/*将x循环右移(从最右端移出的位从最左端移入)n位后得到的值*/
    int wordlength = sizeof(x)*8;
    int rbit;
    if(n % wordlength > 0)
    {
        rbit = (~(~0 << n) & x) << (wordlength - n);
        x = x >> n;
        x = x || rbit;
    }
    return x;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值