位运算

    技术2022-05-20  61

    首先膜拜Matrix67大牛~http://www.matrix67.com/blog/

    1.       六种位运算符

    &:清零特定位,x &= ~(1<<k);

       取特定位,x & (1<<k)

    |: 置1特定位,x |= 1<<k;

    ^: 取反特定位,x &= 1<<k;

    ~: 生成全1掩码,~0

    << 

    >>:算术右移,-2>>1得到-1-1>>1仍是-1java中有单独的逻辑右移>>>)(标准未规定是算术移位,但一般都是)

    建议位运算都使用unsigned类型unsigned int x = 1U<<31; (unsigned int 也可简写为unsigned)

    移位数会mod W,其中W为数据类型长度,因此<<32等于未移位。

     

    2.       应用

    (1)不用temp交换两个数

    X ^= y;   y ^= x;   x ^= y;

    可看做y = x^x^y;   x = x^(y^y);

    而用a = a+b; b = a-b; a = a-b;可能会溢出

     

    (2)求两数的平均值

    (x&y) + ((x^y)>>1)

    (x+y)/2可能溢出

     

    (3)判断一个数是否2的幂

    !(X & (x-1)) && x

    x & (x-1) 消掉x最末尾的1

     

    (4)判断奇偶

    X & 1    等于1为奇

     

    (5)判断二进制表示中1的个数的奇偶性,奇偶校验

    x ^= x>>1; //每一位表示该位和前一位中1的个数的奇偶性

    x ^= x>>2; //每一位表示前4位中1的个数的奇偶性

    x ^= x>>4;

    x ^= x>>8;

    x ^= x>>16; //最后一位表示所有32位中1的个数的奇偶性

    bool r = x&1;

    r = 1表示有奇数个1

     

    (6)计算二进制表示中1的个数

    x = (x & 0x55555555) + ((x>>1) & 0x55555555);//将第12位的数字相加放回1,2

    x = (x & 0x33333333) + ((x>>2) & 0x33333333);

    x = (x & 0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F);

    x = (x & 0x00FF00FF) + ((x>>8) & 0x00FF00FF);

    x = (x & 0x0000FFFF) + ((x>>16) & 0x0000FFFF);

     

    (7)计算二进制表示中前导0的个数 (二分法)

    int n=0;

    if ((x >> 16) == 0) {n += 16; x <<= 16;}

    if ((x >> 24) == 0) {n += 8; x <<= 8;}

    if ((x >> 28) == 0) {n += 4; x <<= 4;}

    if ((x >> 30) == 0) {n += 2; x <<= 2;}

    if ((x >> 31) == 0) {n += 1; x <<= 1;}

    n += !(x >> 31); //!0 等于1

    看了Matrix67博客的留言才意识到n = n+16; 应该写成n += 16;才像话

     

    3.       位域

    struct BS{

    unsigned int a:3;

    int b:3;

    };

    bs.a = 7;         bs.b = 7;

    cout<<bs.a<<bs.b<<endl;

    结果为7 -1,单个位域也分有符号无符号数

     

    4.       C++标准库 bitset

     


    最新回复(0)