位运算

一、概述

运算符 描述 运算规则
& 两位都为1时,结果为1
| 两位都为0时,结果为0
^ 异或 两位相同为0,相异为1
~ 取反 0变1,1变0
>> 右移 各位右移若干位,对于无符号数高位补0,有符号数各编译器处理方法不一,或补符号位(算术右移),或补0(逻辑右移)
<< 左移 各位全部左移若干位,高位丢弃,低位补0

运算优先级:~ > >>, << > & > ^ > |

二、技巧

1、与

1)清零

int n = 10;
n &= 0;

2)奇偶判断

int n = 10;
if((n & 1) == 0)
{
    std::cout << "偶数\n";
}
else
{
    std::cout << "奇数\n";
}

3)取位

例:现有十进制数174(二进制为1010 1110),若想得到其后四位,则将它与第4位为1,其他位为0的数(即二进制数0000 1111,十进制数15)进行运算,结果为十进制数14(二进制为0000 1110)。

int n = 174;
n &= 15;	// n = 14

2、或

1)将指定位设为1

例:现有十进制数174(二进制为1010 1110),若想将其低4位设为1,则将其与二进制数0000 1111(十进制数15)进行运算,结果为十进制数175(二进制为1010 1111),若想将某位设为1,则某个数,这个数这一位为1其他都为0。

int n = 174;
n |= 15;	// n = 175

n = 174;
n |= 16;	// n = 190(二进制:1011 1110)

PS:不同于运算,我们很少用运算进行任意位赋值。通常来讲,我们只使用n | 1把 n 的最后一位强行变成 1,其实质意义是把原数加一。或者使用a | 1 - 1再把它变为 0,这个技巧通常用于把 n 变成 n 最接近的偶数

3、异或

异或符合以下几条性质:

① 交换律
② 结合律 (a ^ b) ^ c = a ^ (b ^ c)
③ 对于任何数 n,都有n ^ n = 0n ^ 0 = n
④ 自反性 a ^ b ^ b = a ^ 0 = a

1)翻转指定位

例:现有十进制数174(二进制为1010 1110),若想翻转其低4位,则将其与二进制数0000 1111(十进制数15)进行异或运算(低4位为1,其他都为0),结果为十进制数161(二进制为1010 0001);若想翻转某一位,则异或一个数,这个数这一位为1其他都为0。

int n = 174;
n ^= 15;	// n = 161

n = 174;
n ^= 16;	// n = 190(二进制:1011 1110)

4、取反

1)与 & 运算配合使一个数最低位为0

int n = 175;	// 二进制:1010 1111
n = (n & ~ 1);	// n = 174

5、右移

1)除法优化

a >> b本质为a / pow(2, b)

int a = 16;
int b = 1;
a >>= b;	// a = 16 / 2 = 8

a = 16;
b = 2;
a >>= b;	// a = 16 / (2 * 2) = 4

6、左移

1)乘法优化

a << b本质为a * pow(2, b)

int a = 2;
int b = 1;
a <<= b;	// a = 2 * 2 = 4

a = 2;
b = 2;
a <<= b;	// a = 2 * (2 * 2) = 8

三、拓展

1、计算一个数二进制中1的个数

// 方法一
int CountOf1(int num)
{
    int count = 0;
    unsigned int flag = 1;

    while(flag)
    {
        if(num & flag)
        {
        	++count;
        }
        flag = flag << 1;
    }
    return count;
}

// 方法二
int CountOf1(int num)
{
    int count = 0;

    while(num)
    {
        num &= num - 1;
        ++count;
    }
    return count;
}

2、判断一个数是否为2的n次方

bool Is2Power(int num)
{
    num &= num - 1;
    if(num)
    {
        return false;
    }
    return true;
}

3、获得最大int值

int GetMaxInt()
{
    return ((unsigned int)-1) >> 1;
}

4、获得最小int值

int GetMinInt()
{
    return 1 << 31;
}

5、交换两个数(不使用临时变量)

void Swap(int &a, int &b)
{
    a ^= b;
    b ^= a;
    a ^= b;
}

6、求一个数的绝对值

int Abs(int n)
{
    return (n ^ n >> 31) - (n >> 31);
}
posted @ 2023-04-14 16:29  HOracle  阅读(64)  评论(0编辑  收藏  举报